Diagnostics
Diagnostic data, severity policies, and the generated code catalogue.
A diagnostic reports a problem in your source or your project. It is data, not an exception. A diagnostic with severity error blocks generation. Nothing is thrown.
Source: packages/compiler/src/Diagnostic.ts, packages/compiler/src/CompilerFault.ts, packages/cli/src/report.ts, docs/specs/0001-compiler-kernel.md.
Shape
interface Diagnostic {
readonly code: string
readonly severity: "error" | "warning" | "info"
readonly message: string
readonly location?: { file: string; line: number; col: number }
readonly related?: ReadonlyArray<Diagnostic>
}| Field | Type | Rule |
|---|---|---|
code | string | numeric EFFX#### or namespaced EFFX[<package>]/#### identifier; validated by DiagnosticCode |
severity | error, warning or info | Severity schema |
message | string | human-readable text |
location | Location, optional | { file, line, col } with integer line and col |
related | Diagnostic array, optional | nested diagnostics, for example the other side of a conflict |
Diagnostic is an Effect Schema, so it serializes. Helpers: error(code, message, location?), warning(code, message, location?) and hasErrors(diagnostics).
What severities do
| Severity | Blocks generation | CLI exit |
|---|---|---|
error | yes. generate is skipped and effx build writes nothing. | 1 |
warning | no | 0 |
info | no | 0 |
Some codes change severity with a setting. For example --strict-access raises the missing-access warning to an error (spec 0006).
Diagnostics are data
Every pipeline stage returns a StageResult: an optional value plus the diagnostics it found. Diagnostics accumulate across stages. The frontend's own diagnostics also travel as data in Collected.
| Type | Shape |
|---|---|
StageResult<A> | { value: Option<A>, diagnostics: Diagnostic[] } |
CompileResult.diagnostics | every diagnostic from every stage, in stage order |
CompilerFault is a different thing. It is a tagged error reserved for IO and invariant failures, such as an unreadable project, a broken cache or a generator bug. A source problem is never a fault (invariant 11, The invariant).
Where you see diagnostics
| Place | Detail |
|---|---|
| Terminal | effx check and effx build print them grouped by file, then a summary line (effx check) |
.effx/manifest.json | effx build stores all diagnostics, with related, in the diagnostics field (effx build) |
| Watch terminal | effx dev prints a full batch and counts for each completed cycle |
| Editor | effx lsp publishes replacements only for open documents; unlocated findings use logs |
Terminal line format:
<code> <severity padded to 8> <message> <file>:<line>:<col>Diagnostics without a location omit the file suffix and are listed last under (no location). inspect and graph do not print diagnostics.
Specifications
The bundled registry documents each diagnostic code. These specs define the compiler contracts:
| Spec | Title |
|---|---|
| 0001-compiler-kernel | Compiler kernel |
| 0002-source-frontend | Runtime surface and TypeScript source frontend |
| 0003-cli-and-vertical-slice | CLI and vertical slice |
| 0005-http-contract-extension | HTTP contract extension |
| 0006-access-contract-extension | AccessContract and required guard bindings |
| 0007-client-and-foldkit | Generated client and Foldkit command adapter |
| 0010-target-profiles-and-emit-modes | Target profiles, declarations and split HTTP emit modes |
| 0013-group-defaults | Group defaults and dense HTTP declarations |
| 0022-persistence-ports | Persistence port declarations and adapter conformance |
Diagnostic code registry
Read the diagnostic code registry for each code, its severity policy, and concrete repairs.
Use effx explain <code> for the same explanation offline. The catalogue comes from the bundled registry, not copied tables.
effx explain EFFX2504
effx explain 'EFFX[@acme/payments]/0001' --config ./effx.config.tsWithout --config, explain uses only the bundled registry. It does not discover or evaluate effx.config.ts, even for unknown codes.
With --config <path>, explain loads that config and its imports, then validates its extension entries. It does not compile project sources.
An invalid explicit config fails even for a bundled code. Project and generation flags, such as --project and --out-dir, are not accepted.
Quote namespaced codes so that the shell does not treat brackets as patterns. Codes are case-sensitive; numeric shorthand is not accepted.
Extension authors supply entries through Extension.diagnosticEntries or the diagnosticEntries option of implement.
The shared @effx/diagnostics renderer can generate a separate catalogue for those entries.