Language Reference

Diagnostic Codes

Every code range, the codes you will actually hit, and what each one means.

Every diagnostic Psy emits has a stable code, a severity, a message, a file, line, column and range, and related locations where they help.

spec/syntax/values.psy:26:9 error PSY4001: `ScalarValues.syntax` must be `string`
but resolved to an object.
    spec/framework.psy:21:5: `syntax` is declared here

Diagnostics are sorted by file, then source position, then code, so output is stable across runs and two runs can be diffed.

Severities are error, warning and info. Errors always fail the command. Whether warnings fail is the diagnostics policy in psy.config.ts.

Ranges

RangeArea
PSY1xxxlexical
PSY2xxxsyntactic
PSY3xxxsemantic
PSY4xxxtypes and composition
PSY5xxxlint
PSY6xxxframeworks
PSY9xxxtooling

Codes are stable across versions.

Lexical — PSY1xxx

CodeMeaning
PSY1001tabs used for indentation
PSY1003unindent matches no enclosing level
PSY1005unterminated interpolation

Syntactic — PSY2xxx

CodeMeaning
PSY2001interpolation contents are not a dotted identifier path
PSY2004invalid declaration keyword
PSY2005as on a concrete spec
PSY2006abstract spec exported without a keyword
PSY2007a block mixes object, list or text content
PSY2011nested spec declaration
PSY2015composition operator used inline
PSY2016malformed module specifier
PSY2017default import
PSY2018namespace import

Semantic — PSY3xxx

CodeMeaning
PSY3001duplicate symbol in the module namespace
PSY3002unresolved reference
PSY3003module not found
PSY3005circular module dependency
PSY3006circular inheritance
PSY3007circular reference
PSY3008unknown declaration keyword
PSY3009duplicate declaration keyword
PSY3011extending something that is not a spec
PSY3012super with no parents
PSY3013no parent defines the property
PSY3014reading a key that does not exist
PSY3015abstract property not implemented
PSY3016abstract property on a concrete spec
PSY3017unknown self field, or self outside a spec
PSY3019duplicate property
PSY3021declaration keyword shadows a reserved word

Types and composition — PSY4xxx

CodeMeaning
PSY4001type mismatch
PSY4002value kind is not composable
PSY4003incompatible composition
PSY4004++ applied to a non-list
PSY4005unknown named type
PSY4006property access on a non-object
PSY4007non-scalar interpolation

Lint — PSY5xxx

CodeRuleDetects
PSY5001noUnusedImportsa name is imported but never used
PSY5002noUnusedSpecsa spec is neither exported nor referenced
PSY5003noUnusedConstsa constant is neither exported nor referenced
PSY5004specNaminga spec or constant name is not PascalCase
PSY5005propertyNaminga property name is not camelCase
PSY5006keywordNaminga declaration keyword is not lowercase kebab-case
PSY5007noUnusedUsea use activates keywords the module never writes

keywordNaming overlaps with PSY2004 — an invalid keyword is already rejected by the parser, so the rule mainly guards tooling that lints partially valid input.

Frameworks — PSY6xxx

CodeMeaning
PSY6001the default code for a framework-reported finding

Frameworks report against the declaration that caused the problem. Morphic's rules are listed in What Comes Out.

Tooling — PSY9xxx

CodeMeaning
PSY9001the config file could not be loaded
PSY9003a file is not canonically formatted (psy format --check)
PSY9004a generated artifact is out of date (psy build --check)
PSY9005unknown or unselected psy init template
PSY9006psy init target directory is not empty

Diagnostics are specified in Psy

Each important failure mode has a diagnostic-rule in the self-specification:

export diagnostic-rule CircularInheritance:
    description:
        Inheritance cycles are rejected.

    code: PSY3006

    condition:
        A spec appears in its own transitive inheritance chain.

    diagnostic:
        Circular inheritance is not allowed.
{
  "CircularInheritance": {
    "code": "PSY3006",
    "description": "Inheritance cycles are rejected.",
    "condition": "A spec appears in its own transitive inheritance chain.",
    "diagnostic": "Circular inheritance is not allowed."
  }
}

The test suite asserts that every diagnostic code an invalid fixture expects is described by one of these rules — so a code cannot exist without a written reason for existing. See Psy Describes Psy.

On this page