flowpactworkflow contracts
Rules

Rules

Every finding flowpact reports, grouped by category. Each code links to why it matters and how to fix it.

Codes have the form <PREFIX><category><nn> — built-in rules use FP, so FP4xx are matrix rules. Severity is configurable per rule; codes never change meaning. Plugin rules use their own prefix (for example ACME101).

Inputs (FP1xx)

CodeNameDefaultSummary
FP101missing-required-input🔴 errorA reusable workflow or local action is called without one of its required inputs.
FP102unknown-input🔴 errorA caller passes an input the reusable workflow or local action does not declare.
FP103input-type-mismatch🔴 errorA literal value passed to a typed workflow_call input has the wrong type.
FP104unused-input🟡 warningAn input is declared but never read anywhere in the workflow or action.
FP105optional-input-no-default-in-condition🟡 warningAn optional input without a default decides an if: condition.
FP106passthrough-dropped🔵 infoA caller passes a value to an input that the callee declares but never reads.
FP107optional-forwarded-to-required🟡 warningA required input of a callee is fed from an optional input that has no default.
FP108undefined-input-ref🔴 errorAn expression reads inputs.\<name\> that the workflow or action does not declare.

Secrets (FP2xx)

CodeNameDefaultSummary
FP201missing-required-secret🔴 errorA reusable workflow is called without one of its required secrets.
FP202unknown-secret🔴 errorA caller passes a secret the reusable workflow does not declare.
FP203unused-secret🟡 warningA workflow_call secret is declared but never read.
FP204secrets-inherit🔵 infosecrets: inherit hands every repository secret to the callee; flowpact lists what is actually needed.
FP205undeclared-secret-ref🔴 errorA reusable workflow reads a secret it does not declare, and some caller does not use secrets: inherit.

Outputs (FP3xx)

CodeNameDefaultSummary
FP301undefined-output-ref🔴 errorAn expression reads an output (needs.*, jobs.*, steps.*) that is never defined.
FP302output-ref-without-needs🔴 errorneeds.\<job\> is read in a job that does not list \<job\> under needs:.
FP303unused-output🟡 warningA job, workflow or action output is declared but no consumer reads it.
FP304step-output-never-written🟡 warningAn output is read from a run: step whose script writes other outputs, but never this one.

Matrix (FP4xx)

CodeNameDefaultSummary
FP401empty-binding-for-matrix-combo🔴 errorAn input passed under with: is empty for some matrix combinations because a matrix key is missing there.
FP402matrix-key-missing-in-combo🟡 warningAn expression reads a matrix key that is only defined in some combinations.
FP403dynamic-matrix-unverified🔵 infoThe matrix is computed at runtime, so flowpact cannot check that every combination defines the keys it reads.
FP404undefined-matrix-key🔴 errorAn expression reads a matrix key that no combination defines (or the job has no matrix).
FP405unused-matrix-shape🟡 warningA matrixShapes entry in the config does not match a job with a runtime-computed matrix.
FP406matrix-too-large🔴 errorA job's matrix produces more than 256 jobs, which GitHub rejects.

Env & expressions (FP5xx)

CodeNameDefaultSummary
FP501undefined-env-ref🟡 warning$\{\{ env.NAME \}\} reads a variable that is not defined at workflow, job or step level, nor written to $GITHUB_ENV earlier.
FP502expression-parse-error🔴 errorA $\{\{ \}\} expression (or an if: condition) cannot be parsed.
FP503schema-violation🔴 errorThe file does not match GitHub’s workflow / action schema (validated with GitHub’s own parser).
FP504yaml-syntax-error🔴 errorThe file is not valid YAML.
FP505context-not-available🔴 errorAn expression uses a context or function that GitHub does not allow in that field (e.g. env in a reusable workflow call’s with:).

Graph structure (FP6xx)

CodeNameDefaultSummary
FP601call-cycle🔴 errorReusable workflows call each other in a cycle.
FP602nesting-depth🔴 errorA chain of reusable workflow calls is deeper than the configured limit (limits.nestingDepth).
FP603remote-unverified🔵 infoA job calls a reusable workflow in another repository; its interface is not verified.
FP604needs-without-data⚪ off (opt-in)A job lists another job under needs: but never reads its outputs or result (opt-in).
FP605large-interface🔵 infoA reusable workflow declares more inputs than limits.maxInputs.
FP606missing-local-target🔴 errorA local uses: ./... points to a workflow or action that does not exist.
FP607unreferenced-reusable-workflow🔵 infoA workflow can only be triggered by workflow_call, but nothing in this repository calls it.
FP608undefined-needs-job🔴 errorA job lists a job under needs: that does not exist.
FP609callee-not-reusable🔴 errorA job calls a local workflow that has no on.workflow_call trigger.

Contracts (FP8xx)

CodeNameDefaultSummary
FP801contract-missing🔴 errorA workflow or local action has no contract in .github/flowpact/ (check mode).
FP802contract-outdated🔴 errorThe locked contract no longer matches the workflow — non-breaking changes to its interface or wiring.
FP803breaking-interface-change🔴 errorA change breaks the locked contract: an input became required, an input/secret/output was removed, or a type changed.
FP804orphan-contract🔴 errorA contract file exists for a workflow or action that no longer exists.
FP805contract-invalid🔴 errorA contract file cannot be read (invalid YAML or schema), usually because it was edited by hand or merged badly.
FP810impact-under-declared🔴 errorThe changes to published workflows or actions need a bigger release than the pull request declares.
FP811impact-declaration-conflict🔴 errorAnother source declares a bigger impact than the one the release tool reads.
FP812impact-over-declared🔵 infoThe pull request declares a bigger impact than its workflow and action changes require.
FP813impact-undeclared🔵 infoNo release impact is declared; flowpact reports the impact the changes require.
FP814impact-uncertain🟡 warningA change to a published unit depends on something flowpact cannot evaluate statically.

Config & overrides (FP9xx)

CodeNameDefaultSummary
FP901override-expired🔴 errorAn override passed its expires date; the findings it suppressed are reported again.
FP902override-unused🟡 warningAn override matches no finding — the problem was fixed, or the target is misspelled.
FP903override-expiring-soon🔵 infoAn override expires within 14 days.

Reserved ranges

  • FP7xx — hygiene rules (reserved).
  • FP8xx — contract drift (contract-missing, contract-stale, breaking-interface-change), shipping with flowpact check.
  • FP9xx — config and overrides (override-expired, override-unused, invalid-config), shipping with overrides.

On this page