.md

Validating a project

dcupl validate is a one-shot health check. It loads a project, classifies any errors it hits, and reports empty or auto-generated models — without starting a long-running daemon. Run it locally against your working files or remotely against a Console version before you push, deploy, or merge.

Note

Validating remotely? The --source remote mode loads a Console version, so it needs project credentials. Pass --project-id / --api-key inline, or configure them once with dcupl config set (see Cloud Sync). Local validation needs no credentials.

Choosing a source

--source selects where the project is loaded from. If you omit it, the CLI infers the source from the flags you pass: --project-id selects remote, otherwise it is local. For a remote run, pass --source remote anyway: the report's source block follows the flag, so an inferred remote run is reported as "mode": "local".

dcupl validate --source local --lc-json dcupl/dcupl.lc.json
Flag Source Purpose
--source <local|remote>bothWhere to load from (inferred if omitted, see above)
--lc-json <path>localPath to the loader config
--project-id <str>remoteConsole project id
--api-key <str>remoteAPI key
--version <id>remoteVersion to load
--cdn-base-url <url>remoteCDN host to load the version from. Defaults to the dcupl CDN, also when consoleApiUrl points at a self-hosted Console, so set it for a self-hosted Console (also DCUPL_CDN_BASE_URL, or cdnBaseUrl in dcupl.config.json)

Processing & performance

Shape how the project is built — apply an application, environments, tags, and variables — and bound the loader's resources.

dcupl validate \
  --app-key web \
  --env production \
  --tag eu,published \
  --var REGION=eu --var TIER=pro

Processing

Flag Purpose
--app-key <str>Application key to load
--env <key>Environment to apply (repeatable)
--tag <tag>Tag filter (repeatable; comma-separate for AND)
--var <KEY=VALUE>Loader variable (repeatable)

Performance

Flag Default Purpose
--auto-servetrueAuto-spawn dcupl serve to load the project
--max-memory <MB>—Cap the loader's memory
--quality <bool>trueRun quality checks
--limit <n>10Max error records in the report

Reading the report

Watch out

validate exits 0 even when the project has errors — it runs in report mode, and the report's top-level ok is always true (it only means "a report was produced"). Do not gate on ok. Parse the JSON and check summary.critical (and load.ok) instead. When no report can be produced — for example a missing or malformed loader config, or dcupl serve not starting — validate prints an error envelope ({"success":false,"error":…,"code":…}) and exits 1, so check the exit code too.

Emit machine-readable output with --json:

zsh — dcupl validate

one-shot health check, machine-readable: dcupl validate --json — output: { "ok": true, "source": { "mode": "local", "loaderPath": "dcupl/dcupl.lc.json" }, "load": { "ok": true }, "models": { "total": 4, "empty": ["Review"], "autoGenerated": [] }, "errors": { "total": 3, "bySeverity": { "critical": 1, "warning": 2 }, "byGroup": { "ResourceError": 1, "PropertyDataError": 1, "ReferenceDataError": 1 }, "byType": { "InvalidResource": 1, "WrongDataType": 1, "RemoteReferenceKeyNotFound": 1 }, "truncatedGroups": [], "records": [ { "title": "http://127.0.0.1:8083/data/missing.data.json", "model": "Review", "errorGroup": "ResourceError", "errorType": "InvalidResource" }, { "title": "Wrong Data Type", "model": "Order", "attribute": "total", "errorGroup": "PropertyDataError", "errorType": "WrongDataType" }, { "title": "Remote Reference Key Not Found", "model": "Order", "attribute": "customer", "errorGroup": "ReferenceDataError", "errorType": "RemoteReferenceKeyNotFound" } ] }, "summary": { "critical": 1, "warnings": 2 } }

✗ summary.critical: 14 models · load ok
1 critical2 warnings
  • critical

    http://127.0.0.1:8083/data/missing.data.json

    Review · ResourceError / InvalidResource

  • warning

    Wrong Data Type

    Order.total · PropertyDataError / WrongDataType

  • warning

    Remote Reference Key Not Found

    Order.customer · ReferenceDataError / RemoteReferenceKeyNotFound

Models:empty · Reviewauto-generated · none

The same report, decoded — errors.records[] with the severity of each errorGroup, plus the empty and auto-generated model signals (models.empty, models.autoGenerated).

The counts are exact: errors.total, bySeverity, byGroup, and byType are summed from the SDK's $DcuplErrorTrackingSummary model. errors.records[] is only a sample (--limit, default 10), and error tracking stores at most 1000 records per error group. Every group that hit that cap is listed in errors.truncatedGroups as { model, attribute, errorType, totalCount, storedCount }, and the text output repeats them under Truncated groups. An empty array means nothing was capped.

Gate a script on the exit code, load.ok and the critical count — and on summary.warnings too when warnings should block:

# exit 1 = no report (e.g. the loader config could not be loaded)
report=$(dcupl validate --json) || { echo "$report"; exit 1; }

# gate on load + critical count — warnings won't block
loaded=$(echo "$report" | jq -r '.load.ok')
critical=$(echo "$report" | jq -r '.summary.critical')
if [ "$loaded" != "true" ] || [ "$critical" -gt 0 ]; then
  echo "Validation failed: load.ok=$loaded, $critical critical error(s)"; exit 1
fi

# stricter: warnings block too
warnings=$(echo "$report" | jq -r '.summary.warnings')
[ "$warnings" -gt 0 ] && { echo "$warnings warning(s)"; exit 1; }

Error severity

Each record carries an errorGroup, errorType, model, attribute, and title. Groups roll up into two severities.

Severity Error groups Meaning
CriticalModelDefinitionError, ResourceError (and any error group not listed here)The workspace can't load or a model is malformed — blocks everything downstream. Must fix.
WarningReferenceDataError, PropertyDataError, DataContainerErrorData-level issues (stray foreign keys, type mismatches). May resolve as more data loads.