Documentation
Troubleshooting
Runtime-offline desired-state analysis for Argo CD GitOps repositories.
Start with the symptom. Run the smallest command that exercises the failing
path, then add --strict when warnings should fail the run or -o json /
-o yaml when another tool needs stable diagnostics.
drydock get apps --path .
drydock test apps --path .
drydock diag --path .
Symptom: No Applications Discovered
Check that the selected --path points at the GitOps repository root or pass
the directory that contains Argo CD objects. If the repository stores bootstrap
inputs as Kustomize rather than committed inflated objects, add an explicit
entrypoint:
drydock get apps --path . --discover-kustomize clusters/prod/argocd
If the repository uses ApplicationSet providers, make sure the workflow passes the same fixture inputs used for local verification.
Symptom: ApplicationSet Warns And Generates Zero Applications
An appset.template-render-failed warning means template execution failed for
that ApplicationSet, so it contributes no Applications — the same outcome the
Argo CD controller reports as an ErrorOccurred condition. A common cause is
a Git files generator matching an empty or comment-only param file while the
template references file params under missingkey=error: an empty file
decodes to one empty param set, matching Argo CD. If a matched file should
generate nothing, make its content []. Use --strict when the warning
should fail the run.
In one-sided diffs, the failing side’s zero desired Applications appear as additions or deletions, while the live controller would abort reconciliation without pruning.
Symptom: Discovery Fails Decoding Non-Deployable YAML
Discovery errors that end with
(use --discover-ignore to exclude non-deployable manifests from discovery)
mean the scan found YAML it could not decode, such as unrendered chart
templates or scaffolding committed alongside real Argo CD objects:
templates/scaffold.yaml: decode ApplicationSet: json: cannot unmarshal string
into Go struct field ... of type int64 (use --discover-ignore to exclude
non-deployable manifests from discovery)
If the file is not deployable Argo CD intent, exclude it from discovery with a repository-relative glob:
drydock test apps --path . --discover-ignore 'templates/**'
Matching files are skipped before decoding, even when named by explicit app manifest paths. If the failing file is a real Application manifest, fix the manifest instead; ignoring it hides it from every discovery-based command.
Symptom: Render Fails In CI But Works Locally
Confirm whether CI has the same source access and caches. Default runs may
fetch declared Git, Helm, OCI Helm, OCI artifact, and remote Kustomize
sources into drydock caches. --offline disables those source network fetches and requires local
files, repo maps, or existing cache entries.
drydock test apps --path . --offline
drydock diag --path . --cache-events
--cache-events renders Applications so source-acquisition events match the
rendering path.
Symptom: Self-Repo Values Render From The Remote / Values ENOENT On Renders
A source whose repoURL is the checkout’s own repository — commonly a
ref-only $repo source supplying Helm value files — should resolve to the
local tree on every render surface (get, build, test, diag, and both
diff sides). If such a source instead fetches remotely, renders miss files
that exist only locally (for example, a pull request’s new values file fails
with a not-found error, or edits are silently ignored).
Two remediations:
-
Upgrade drydock (older releases resolved self-repository sources only during diffs) and make sure
refs/remotes/origin/HEADexists so drydock can learn the default-branch name —git clonesets it, and the pr-action records the pull request’s base branch there whenever a base ref is known (pull-request events, or an explicitbase-refinput). For bareactions/checkout-style checkouts outside the pr-action, set it from the default branch the workflow already knows:- run: >- git remote set-head origin "${{ github.event.repository.default_branch }}"That is local-only but needs
refs/remotes/origin/<default-branch>, which afetch-depth: 0checkout provides.git remote set-head origin -aqueries the remote instead, so it needs credentials that a checkout withpersist-credentials: falsedoes not leave behind.Without that symref, sources pinned to the default-branch name acquire remotely — drydock never guesses the default branch from
init.defaultBranchor the checked-out HEAD. -
Use
--repo-map URL=PATHwhen detection cannot apply: fork-shaped URLs (watch for thesource.self-repo-near-misswarning), commit-SHA pins, or runs from a subdirectory of the checkout (--path <subdir>does not walk up to the enclosing.git).
The flip side of local resolution: a self-repository source path that was
deleted locally fails path-not-found even though the remote tip still has it —
the local tree is the desired state.
Symptom: OCI Source Renders The Local Checkout Or Fails With load helm chart .
A first-class OCI artifact source — any repoURL: oci://... — has two
historical failure modes on older drydock releases, which did not classify
oci:// URLs:
- With a
helm:block, the render failed with an error likeload helm chart ., because the local repository root was treated as the chart directory. - Without a
helm:block, the run silently succeeded but rendered the LOCAL checkout as plain manifests (path: .always exists locally), not the artifact content.
Upgrade drydock: current releases classify every oci:// source before local
path resolution, resolve the revision to a digest, and render the pulled
artifact content. If you added --repo-map of the oci:// URL as a
workaround, it still wins over registry acquisition — remove it when you want
the artifact fetched, keep it when a local checkout of the content should be
rendered instead.
Related shapes on current releases:
chart:on anoci://source is ignored, as in Argo CD, and reported assource.oci-chart-ignored— see the next symptom.- An OCI URL as a
$refvalue-file source fails clearly; Argo CD supports Git-only$refsources. - An
offline cache misserror under--offlinemeans the digest, tag, or constraint was never resolved online against this cache directory — run once without--offlineto warm the image cache and tag records.
Symptom: source.oci-chart-ignored, Or An oci:// + chart: Source Is Not Found
An Application whose repoURL starts with oci:// and also sets chart::
source:
repoURL: oci://ghcr.io/bjw-s-labs/helm/app-template
chart: app-template
targetRevision: 5.2.1
Argo CD’s repo-server dispatches every oci:// URL as an OCI artifact source
before it considers Helm, so it pulls repoURL itself at targetRevision
and never reads chart:. Current drydock releases do the same and report one
advisory warning per Application source:
warning source.oci-chart-ignored: Application argocd/app source[0] chart="app-template": chart "app-template" is ignored: Argo CD treats every oci:// repository URL as an OCI artifact source and pulls oci://ghcr.io/bjw-s-labs/helm/app-template at revision "5.2.1" without reading spec.source.chart, so drydock renders that artifact; to silence this warning drop chart and set path: . (Argo CD requires path or chart on every source, or ref in a multi-source list); only if you meant the chart named "app-template" under repository ghcr.io/bjw-s-labs/helm/app-template, switch to the schemeless Helm OCI shape (repoURL "ghcr.io/bjw-s-labs/helm/app-template", chart "app-template")
The warning is advisory: --strict neither escalates it nor fails on it, the
manifests are identical with or without it, and the Argo CD render parity
smoke pins the shape live. Two remedies, both Argo-valid:
- Keep the artifact: drop
chart:and setpath: .(Argo CD requirespathorcharton every source, orrefin a multi-source list). - Keep a chart under a repository: switch to the schemeless Helm-OCI shape,
repoURL: ghcr.io/bjw-s-labs/helmpluschart: app-template, which uses the Helm registry client and the chart cache.
Older drydock releases pulled <repoURL>/<chart>:<version> for this shape
instead. A source that relied on that now pulls repoURL:targetRevision,
which fails with resolve OCI artifact ... not found or an
authenticate OCI artifact ... error (registries answer 401/403 for private
and for nonexistent repositories alike); the warning is printed alongside,
and the schemeless remedy above restores the previous pull.
Credential errors surface at the first oci:// acquisition and name the
flag. --registry-config "<path>" does not exist means the path is wrong —
runs without OCI artifact sources never open the file, so this appears only
on OCI pulls. the credential for <host> is an identity token means the
file’s entry came from a token login that the OCI artifact client cannot
present; log in to that registry with a username and password or pass
--oci-username/--oci-password. An error naming
docker-credential-<helper> means the file routes that host through a
credential helper that cannot run here; use a plain auths file or the
--oci-* flags.
Under --offline, including the pr-action’s offline input, an Application
that moved from the chart flow to the artifact flow fails with
offline cache miss until one online run with --oci-cache-dir warms the
image cache and tag records:
drydock build apps --path . --oci-cache-dir /var/cache/drydock-oci
drydock build apps --path . --oci-cache-dir /var/cache/drydock-oci --offline
Its earlier chart-cache entries are orphaned; drydock cache prune --source chart removes them.
Symptom: Changed-Only Falls Back To All Apps
Multi-Application diffs use changed-only selection by default. If a changed file cannot be safely mapped to Application inputs, non-strict mode warns and renders all Applications. Use strict mode when ambiguous ownership should fail:
drydock diff apps --repo . --ref HEAD --ref-orig main --strict-changed-only
If the unowned file is one an exec or container plugin reads, declare it in the
plugin Application’s argocd.argoproj.io/manifest-generate-paths annotation
so changed-only selects that Application instead of rendering all. Declare it
too when a plugin reads a file another Application owns, through its graph or
its own annotation: changed-only then renders only that owner, and strict mode
does not catch the omission. See
Declare plugin inputs
.
A changed Argo CD setting that every render or diff reads also renders all
Applications, with diff.changed-only-settings: the tracking method, resource
exclusions, compare options, an ignoreDifferences customization, or a CMP
definition, for example. A repository or cluster Secret change does not,
unless the Secret enables OCI for an OCI repository URL: it selects only the
Applications that use it (diff.changed-only-settings-scoped). Neither it nor
a setting no output reads excuses an unowned changed path, which still renders
all Applications and fails --strict-changed-only.
Symptom: Plugin Source Fails Closed
The CLI and default Go client do not execute config management plugin commands
by default. Safe Kustomize wrapper plugins and argocd-vault-plugin
compatibility may render natively. Exec or container plugin rendering needs
trusted drydock plugin policy, trusted policy provenance, and
--enable-plugins.
drydock plugin-policy doctor --path .
drydock test apps --path . --plugin-policy-ref main --enable-plugins
Use plugin-policy doctor to check whether drydock sees the plugin policy,
native compatibility options, trusted provenance, and command execution gates.
Then add trusted plugin flags only when the render actually needs exec or
container plugin commands.
If plugin-rendered bootstrap apps are missing, check PluginPolicy
bootstrap.entrypoints. Static discovery mode disables those entrypoints;
--max-discovery-depth 0 does not.
See Plugin policy for the operator gate.
Symptom: Diff Noise Is Hiding Or Showing Too Much
drydock hides common Helm chart/version labels and pod-template checksum
annotations by default. Use --show-ignored-fields to inspect them, or
--strip-attr KEY to remove additional label or annotation keys before
comparison.
Symptom: PR Comment Is Too Large Or Hard To Scan
Use markdown output for the review surface and keep full artifacts for deeper inspection:
drydock diff apps --repo . --ref HEAD --ref-orig main -o markdown
drydock diff images --repo . --ref HEAD --ref-orig main -o markdown
For sensitive or noisy resource classes, use explicit filters such as
--skip-secrets, --skip-crds, or repeatable --strip-attr KEY.
For deeper reference, see the reference hub , Compatibility , and Source acquisition .