---
title: Diagnostics
editUrl: https://github.com/Cratis/Arc.TypeScript/edit/main/Documentation/reference/diagnostics.md
description: Every place Arc for TypeScript reports a problem, from lint rules and proxy generation to build errors, validation reasons, HTTP status codes, and the endpoints and telemetry of a running server.
---


Arc reports a problem at the earliest point it can see it. A binding mistake shows in the editor, a missing service stops `build()`, a bad request answers 400 with a reason, and a running server can describe what it serves. This page lists each of those surfaces and what it tells you. For step-by-step fixes of common problems, see [Troubleshooting](/arc/backend/typescript/troubleshooting/).

## In the editor: lint rules

`@cratis/eslint-plugin-arc-core` checks model-bound artifacts before you build. Enabled rules report as errors. Both presets include bounded Chronicle checks for reactor and command appends and unmasked secret-looking fields when Chronicle is installed; `recommended-type-checked` also includes reactor replay decisions and the Guid response check. `query-argument-name` is opt-in. Rules that match a .NET analyzer keep its `ARC` or `ARCCHR` code. Setup is in [Code analysis](/arc/backend/typescript/code-analysis/).

| Rule | Reports |
| --- | --- |
| [`arc0002`](/arc/backend/typescript/code-analysis/arc0002/) | A command-like class without `@command()` |
| [`arc0003`](/arc/backend/typescript/code-analysis/arc0003/) | Command handling outside the command |
| [`arc0004`](/arc/backend/typescript/code-analysis/arc0004/) | A command without a public instance `handle()` |
| [`arc0005`](/arc/backend/typescript/code-analysis/arc0005/) | A value from `provide()` that `handle()` never consumes |
| [`arc0010`](/arc/backend/typescript/code-analysis/arc0010/) | A synchronous command result wrapped in a promise |
| [`arc0012`](/arc/backend/typescript/code-analysis/arc0012/) | A built-in error thrown from an artifact |
| [`arc0014`](/arc/backend/typescript/code-analysis/arc0014/) | A query with type parameters |
| [`arc0015`](/arc/backend/typescript/code-analysis/arc0015/) | An incoming parameter converted to a concept inside the query |
| [`arc0019`](/arc/backend/typescript/code-analysis/arc0019/) | `@allowAnonymous()` combined with `@authorize()` or `@roles()` |
| [`arcchr0003`](/arc/backend/typescript/code-analysis/arcchr0003/) | Direct reactor appends to its own default event log |
| [`arcchr0006`](/arc/backend/typescript/code-analysis/arcchr0006/) | Returned Arc commands from live reactor handlers without a replay decision (type-checked preset) |
| [`arcchr0007`](/arc/backend/typescript/code-analysis/arcchr0007/) | Direct default-log appends from a command's `handle()` or `provide()`, including injected Chronicle services and `.transactional` appends |
| [`arcchr0009`](/arc/backend/typescript/code-analysis/arcchr0009/) | Unmasked secret-looking command fields and constructor parameter properties when Chronicle resolves |
| [`arcchr0010`](/arc/backend/typescript/code-analysis/arcchr0010/) | A keyless command returning a type-checked Fundamentals `Guid` value beside a direct decorated event (type-checked preset) |
| [`missing-field`](/arc/backend/typescript/code-analysis/missing-field/) | A model-bound property without `@field` |
| [`declared-field`](/arc/backend/typescript/code-analysis/declared-field/) | A decorated field that would not be emitted |
| [`inject-binding`](/arc/backend/typescript/code-analysis/inject-binding/) | `@inject` tokens that do not match the handler's parameters |
| [`query-binding`](/arc/backend/typescript/code-analysis/query-binding/) | `@query` descriptors that do not match the method's parameters |
| [`query-argument-name`](/arc/backend/typescript/code-analysis/query-argument-name/) | A query wire name that differs from its parameter name (opt-in) |
| [`misplaced-decorator`](/arc/backend/typescript/code-analysis/misplaced-decorator/) | An Arc decorator on an artifact that does not support it |
| [`unexported-artifact`](/arc/backend/typescript/code-analysis/unexported-artifact/) | A decorated artifact that discovery cannot see because it is not exported |
| [`validator-target`](/arc/backend/typescript/code-analysis/validator-target/) | A validator without `@validator(Target)` when no generated metadata names it |

[Chronicle code analysis](/arc/backend/typescript/chronicle/code-analysis/) maps the remaining .NET diagnostics to TypeScript checks or review concerns.

## At generation: arc-proxygenerator

- The CLI exits with code 1 and prints the error when generation fails, such as for a type it cannot map or a dynamic decorator option. See [Type mapping](/arc/backend/typescript/proxy-generation/type-mapping/).
- A validator rule that needs server evaluation, such as `must` or `when`, stays on the server, and the generator prints a diagnostic naming it. See [Validation rules](/arc/backend/typescript/proxy-generation/validation/).
- `--check-metadata` compares the generated metadata file with the source and fails when they differ, without generating anything; it prints `Generated artifact metadata is current` when they match. See [Generated artifact metadata](/arc/backend/typescript/proxy-generation/generated-artifact-metadata/).

## At startup: build() and registration

`builder.add(...)`, the `with...` integrations, and `builder.build()` refuse an application that cannot run correctly, instead of failing on the first request. Typical messages:

| Message | Meaning |
| --- | --- |
| `Not an Arc artifact: <Type>` | A class passed to `add()` has no Arc or integration decorator |
| `Conflicting namespaces for <Type>` | One class was registered under two different namespaces |
| `Duplicate validator target: <Type>` | Two validators target one class |
| `Unbound handle parameters on <Type>.handle; use builder.useGeneratedMetadata(metadata) or @inject(...); default and rest parameters require explicit binding` | A command's `handle()` has parameters without generated metadata or `@inject(...)` tokens; see [Troubleshooting](/arc/backend/typescript/troubleshooting/#build-fails-with-unbound-handle-parameters-or-missing-parameter-metadata) |
| `Unbound provide parameters on <Type>.provide; use builder.useGeneratedMetadata(metadata) or @inject(...); default and rest parameters require explicit binding` | The same for a command's `provide()` |
| `Unbound parameters on <Type>.<method>` | A query's `@query(...)` descriptors do not cover every parameter of the method |
| `Missing parameter metadata for <Type>.<method>; use explicit tokens` | A bare `@query()` or an empty `@inject()` on a method with parameters, without generated metadata, in standard decorator mode |
| `Unbound constructor parameters on <Type>` | A service's constructor parameters have no tokens |
| `Service <Token> requires an implementation` | A `serviceToken` was registered without a class or factory |
| `Missing service: <Token>` | A declared dependency is not registered |
| `Service dependency cycle: <Token>` | Services depend on each other in a loop |
| `Captive service dependency: <Token>` | A singleton depends on a scoped or transient service |
| `Expected one read-model resolver for <Type>, found <n>` | A `commandReadModel(Type)` has no owning integration, or two; see [When read model resolution fails](/arc/backend/typescript/chronicle/read-models/failures/) |
| `Multiple identity details providers found` | More than one `@identityDetailsProvider()` |
| `Import @cratis/arc.<name> before calling with<Name>()` | An integration method was called without importing its package |
| `Chronicle requires eventStore and exactly one of connectionString or client` | Incomplete `withChronicle` options or configuration |
| `MongoDB requires exactly one of client, server, or serverResolver` | Incomplete `withMongoDB` options or configuration |
| `Drizzle requires exactly one of database or databaseFactory` | Incomplete `withDrizzle` options |
| `Invalid Cratis configuration: <path>.<problem>` | An `appsettings.json` or `Cratis__...` value has the wrong type; the message names the key, never the value |

The service messages are explained in [Dependency injection](/arc/backend/typescript/dependency-injection/).

## At request time: results and status codes

A command or query result carries `validationResults`, and each result has a `reason`:

| `reason` | Meaning |
| --- | --- |
| `rule` | A validator rule failed, or a required command read model is missing or has no key |
| `malformedRequest` | The input does not match the declared fields |
| `validatorFailed` | A validator threw; the error goes to `logger`, and the caller sees a generic message without the exception text |
| `dependencyUnavailable` | A service a validator or handler needs could not be resolved |
| `constraintViolation` | Chronicle rejected an append for a constraint; `reasonDetail` names it |
| `concurrencyViolation` | Chronicle rejected an append because the stream moved; `state` holds the revisions |

The HTTP status follows the [HTTP contract reference](/arc/backend/typescript/reference/http-contract/#status-codes): 400 for validation, 401 and 403 for authentication and authorization, 405 for an unsupported method, 408 and 503 for observable waits and limits, and 500 for exceptions. Outside development, a 500 carries `An unexpected error occurred` and no stack trace; the original error goes to the `logger` option. See [Configuration](/arc/backend/typescript/configuration/#errors-and-logging).

## On a running server

| Surface | Shows |
| --- | --- |
| `GET /.cratis/commands`, `GET /.cratis/queries` | Every command and query with its route and input JSON Schema; see [Introspection](/arc/backend/typescript/introspection/) |
| `GET /.cratis/identity-details/schema` | The identity details schema |
| `GET /openapi.json` | The OpenAPI 3.1 document; see [OpenAPI](/arc/backend/typescript/open-api/) |
| `GET /.cratis/queries/health` | The authenticated caller's own observable hub connections, when `query.enableObservableHealth` is on; see [Query health](/arc/backend/typescript/queries/query-health/) |
| OpenTelemetry | Spans such as `cratis.arc.command.execute` and the `cratis.arc.command.duration` / `cratis.arc.query.duration` histograms in seconds from the versioned `Cratis.Arc` scope; `cratis.arc.operation.duration` remains emitted but is deprecated; see [Observability](/arc/backend/typescript/observability/) |
| `logger(error, correlationId)` | Every failure with its correlation ID, and unknown configuration keys |

Every response carries its correlation ID, in `X-Correlation-ID` unless you renamed the header. Search your logs and traces by it.

For the Chronicle side of a running system, such as failed observer partitions, use the Chronicle Workbench or the `cratis` CLI against the same event store and tenant namespace.

## Related

- [Troubleshooting](/arc/backend/typescript/troubleshooting/)
- [Capability reference](/arc/backend/typescript/reference/capabilities/)
- [Glossary](/arc/backend/typescript/reference/glossary/)
