Skip to main content

Validation errors

.loha.yml goes through several checks before any pipeline runs: a YAML security pass, Zod schema validation, task-reference validation, and finally (only when a build is triggered) task parameter binding. This page lists the errors from each and the most common cause for each.

Validation is not the whole gate

The dashboard editor, loha validate, and the MCP validate_pipeline tool all run the parser and the task-reference check. They do not check with: parameter names, which are bound only when a build starts.

So a config can validate cleanly and still fail, or worse, succeed while silently ignoring a parameter you set. See Task parameter errors.

Auto-synced

This page is kept in lockstep with the parser source (packages/pipeline-config) by the loha-docs-sync skill. New errors added to the parser must land with a doc entry here.

YAML / document errors​

Raised by the YAML security pass before the schema is even checked.

ErrorCauseFix
YAML document exceeds maximum size (1MB)The file is larger than 1 MBTrim the file: 1 MB is a hard cap
Custom YAML tags are not allowedThe document contains !! (e.g. !!python/...)Remove the tag: only standard scalar/sequence/map types are allowed
Too many YAML anchors (max 100)More than 100 &anchor definitionsReduce anchor reuse; this is an anti-attack limit
Too many YAML aliases (max 100)More than 100 *alias referencesReduce alias reuse; this is an anti-attack limit
Invalid YAML: must be an objectThe top level isn't a mappingThe document must start with version: etc., not a list or scalar
project: not a valid key — …The config declares a project:Remove it. A repository's project is set by where you link it in Loha, not in the file
(a raw YAML syntax message)e.g. bad indentation of a mapping entry at line 7, column 3Passed through verbatim from the YAML parser. Fix the indentation or quoting at the reported line

Schema errors​

Raised by Zod after the YAML parses. Each is prefixed with a path into the document, e.g. jobs.build.steps.0.name: Required.

ErrorCauseFix
version: Invalid literal value, expected 1 | "1"version missing or not 1Set version: '1' at the top
name: String must contain at most 128 character(s)Pipeline name too longShorten it
name: Invalidname has characters outside a-z A-Z 0-9 _ -Use only alphanumerics, dashes, underscores
Must have between 1 and 20 jobsZero jobs, or more than 20Stay within the 1–20 range
Unrecognized key(s) in object: '<key>'An unknown field inside jobs: or steps:Remove it, or check for a typo in the field name
<path>.name: RequiredA step is missing its required nameEvery step needs a name
Step must have either "uses" or "run", but not bothA step set neither, or both, of uses / runPick exactly one
Timeout must be a number followed by a unit: s, m, h, or d (e.g., "30m")A timeout value isn't in the <number><unit> formUse values like 30s, 10m, 2h, 1d
The error you won't get

Only jobs: and steps: reject unknown keys. The top level and the on: block silently discard them, so branch: instead of branches: produces no error at all. It parses to an empty filter, which matches every branch. See Unknown keys are dropped in silence.

Job artifact errors​

Raised for artifacts:. The first group is checked when the file is validated, the second when the build is triggered, and the last while the job runs.

ErrorCauseFix
Artifact path "<path>" is absolute. Use a path relative to the repository root, such as "dist/".An artifacts.paths entry starts with /Write the path relative to the workspace root
Artifact path "<path>" contains a ".." segment. …An entry climbs out of the workspaceRemove the .. segment
Artifact path "<path>" contains a backslash. … / … contains a control character. …An entry uses \ or a control characterUse / separators and plain characters
Unrecognized key(s) in object: '<key>' (under artifacts)artifacts: has a key other than pathsKeep only paths. There is no per-job expiry
Step name "<name>" is reserved for Loha's artifact steps ("artifacts-save" and "artifacts-restore"). Rename it.A step is named artifacts-save or artifacts-restoreRename the step
Job "<id>" has a name too long for artifacts (...; the limit is 45). Shorten the job id.A job that saves or restores files has an id over 45 characters after normalisingShorten the job id
Jobs "<a>" and "<b>" both become the artifact name "<name>". Rename one of them.Two job ids normalise to the same nameRename one of the jobs
ARTIFACTS_UNAVAILABLE: This pipeline passes files between jobs (artifacts:), but artifact storage is not available on this deployment.The build was refused at trigger time: the deployment has no artifact storageAsk your Loha administrator to enable artifact storage, or remove the non-empty paths
Declared artifact path '<entry>' matched no files in job <jobId>.A declared path or glob matched nothing when the job finished. The job failsFix the path, or make the job produce the files. Use paths: [] if it hands nothing on
Job outputs are <n> bytes; the limit is <n> bytes per job.The job's archive is over 1 GiBDeclare fewer or smaller paths
This workspace has used its artifact storage; delete old artifacts or raise the limit.The archive does not fit in the workspace's artifact quotaDelete old artifacts from the Artifacts page, or ask for a higher limit
Could not restore job outputs (409 JOB_OUTPUTS_NOT_READY).An upstream job's archive exists but never finished uploading, or its upload failed. The receiving job fails rather than running without the filesRe-run the build. If the upstream save step failed, fix that first
Could not restore job outputs (410 JOB_OUTPUTS_GONE).An upstream job's archive was deleted, usually after the retention windowRun a new build

Task reference errors​

Raised when a uses: value doesn't resolve to an official task. These are checked by the parser, the dashboard editor, and validate_pipeline.

ErrorCauseFix
Invalid task reference "<ref>". Expected 'loha/<task-name>' or 'loha/<task-name>@v1'.Malformed uses: valueUse the loha/<task>@v1 form
Unknown task provider '<x>' in '<ref>'. This looks like GitHub Actions syntax. Use '<loha-task>' instead.e.g. actions/checkoutUse the suggested Loha task
Unknown task provider '<x>' … with no Loha task equivalent. Use a 'run:' step …e.g. actions/setup-nodeExpress it as a run: step, or pick the step's image:
Unknown task 'loha/<x>'. Available tasks: …Task name typo, or a task that doesn't existCheck the catalog

Task parameter errors​

Raised when the build is triggered, not during validation.

ErrorCauseFix
Required parameter '<NAME>' not provided for task '<task>'. Set it in the 'with:' field of your .loha.yml step.A required parameter is missingAdd it: the task's catalog page lists which are required
Denied environment variable names: <list>. These cannot be overridden.env: sets a protected variableRename it (see below)
Image '<img>' is not on the allowed image list.A step or service image: outside the allowlistSee Allowed images
Job '<job>' service '<name>' is not a valid name. …A service name is not a DNS labelUse lowercase letters, digits and hyphens
Job '<job>' service '<name>' requests resource class '<class>', which is not enabled for this workspace. …A service asks for a class your plan does not allowUse an allowed class, or omit it for the micro default
Job '<job>': matrix produces N combinations, which exceeds the limit of 20. …A matrix is too wideReduce an axis or split the job
Job '<job>': matrix axis '<axis>' has no values. …A matrix axis is an empty listGive it at least one value, or remove the axis
Pipeline expands to N jobs, which exceeds the limit of 20. …Jobs plus matrix instances exceed the ceilingReduce a matrix or split the pipeline
<where> references '${{ matrix.<axis> }}', but no matrix axis named '<axis>' is defined for this job.A matrix reference with no matching axis (a typo, or used in a job with no matrix)Fix the axis name, or add it to strategy.matrix
timeout must be a valid Kubernetes duration (e.g. 30s, 10m, 2h, 1d)Malformed timeout at trigger timeUse the <number><unit> form
timeout exceeds the maximum of <n>s (24h); requested <n>sTimeout over the 24-hour ceilingLower it
A wrong with: key produces no error at all

Parameter binding iterates the task's declared parameters. A with: key the task doesn't declare is dropped silently. The build succeeds and simply doesn't do what you asked. This is the single most common way a copied example misbehaves.

Always check the parameter names on the task's catalog page.

Protected environment variable names, rejected case-insensitively in env:: PATH, HOME, SHELL, USER, LD_PRELOAD, LD_LIBRARY_PATH, NODE_OPTIONS, NODE_PATH, PYTHONPATH, PYTHONSTARTUP, RUBYOPT, PERL5OPT, JAVA_TOOL_OPTIONS, BASH_ENV, ENV, CDPATH, IFS, LOHA_TOKEN, LOHA_API_URL.

Environment errors​

Raised when the build is triggered, not during validation: they depend on the project's environments, which the parser cannot see. The build fails before any step runs. See environment variables.

ErrorCauseFix
jobs.<job>.environment "<name>" is not an environment of this project. Environments: <list>.environment: names an environment the build's project doesn't haveUse one of the listed names, or create the environment
jobs.<job>.environment "<name>" cannot be used: this project has no environments.The project has no environments yetCreate the environment, or remove environment:
jobs.<job>.environment is set to "<name>", but environment-scoped variables are not enabled for this workspace. …Environment variables are not enabled for your workspace yetRemove environment:, or ask a workspace administrator
The trigger's default environment is not an environment of this build's project. …The trigger's Default environment belongs to another projectPick a default environment from this project on the trigger
This build targets an environment, but it has no project to look environments up in.The build has no projectRemove environment:

working_directory errors​

working_directory must be a safe relative path, though note it is validated but not applied: every step currently runs in /workspace/source regardless. These errors still fire.

ErrorCauseFix
Null bytes not allowed in working_directoryThe path contains a null byteRemove it
Absolute paths not allowed in working_directoryThe path starts with /Use a path relative to the workspace
Path traversal (..) not allowed in working_directoryThe path contains a .. segmentRemove the traversal

run script errors​

run scripts are scanned for commands that would breach workspace isolation.

ErrorCauseFix
Accessing Kubernetes service account token is not allowedThe script reads /var/run/secrets/kubernetes.ioDon't touch the service account token
Accessing instance metadata endpoint is not allowedThe script hits 169.254.169.254 or fd00:ec2:Don't read cloud instance metadata
Direct Vault/OpenBao API access is not allowed in run scriptsThe script calls Vault/OpenBao directlyUse Loha variables and secrets instead
Piping remote content to shell is not allowedThe script pipes curl/wget output into a shellDownload, inspect, then run. Don't pipe to sh

These patterns are matched textually across the whole script, so they can fire on innocent content: a script that merely mentions 169.254.169.254, or one containing both the words "vault" and "kv", is rejected with no override. Rephrase the script, or move the affected logic into a task.

The scan applies to run: scripts only. It does not inspect env: values or with: parameters, so it is a guardrail against accidents rather than a security boundary.

What's not yet covered​

  • Translation of error messages into Thai is on the v0.5.0 roadmap
  • Live linting in the dashboard's .loha.yml editor catches schema errors as you type; deeper IDE-grade tooling is on the roadmap