Troubleshooting
Description
Messages are grouped by theme and quoted as Updatecli prints them, so searching this page for the line in your log should land on the right entry.
Before anything else, two things resolve most of what follows:
--debugRaises the log level. Several decisions (which token was used, which engine was selected, why a target was skipped) are logged at debug level only.
updatecli pipeline diffParses and validates the whole manifest and reports what would change without writing anything. Every validation error on this page surfaces from a
diff, so there is no need to risk anapplyto find them.
Note | Debug mode also switches itself on when Updatecli runs inside a CI system that reports being in
debug mode. When it does, it says so: CI pipeline detected in Debug Mode - hence enabling debug
mode. Jenkins, GitLab CI, and GitHub Actions are detected, see
"Environment variables". |
Authentication
no access token found
failed to get access token: no access token foundNothing supplied a GitHub token. Updatecli looks in this order and stops at the first hit:
spec.tokenon the resource or scmUPDATECLI_GITHUB_TOKEN, optionally withUPDATECLI_GITHUB_USERNAMEthe GitHub App variables (
UPDATECLI_GITHUB_APP_CLIENT_IDand friends)GITHUB_TOKEN, the fallback that makes GitHub Actions work without extra configuration
Run with --debug to see which one was picked, each path logs its own line, such as using GitHub
token from environment variable UPDATECLI_GITHUB_TOKEN. Silence from all four means none was set.
The full list is on the "Environment variables" page.
you cannot use both token and app authentication methods
A single GitHub spec carries both token and app. Pick one. A personal access token and a GitHub
App are alternatives, not layers.
github parameter(s) required: [owner,repository]
The GitHub spec is missing owner, repository, or both. The message lists exactly which.
unclear configuration, better safe than sorry
This one deserves an explanation, because the message alone does not give you the fix. It is preceded
in the log by a longer block beginning Better safe than sorry.
It means Updatecli was about to force-push to a branch that is not a generated working branch, so
git push --force would land directly on, say, main. Rather than guess, it refuses.
Either let Updatecli use a working branch (the default), or, if pushing straight to that branch is genuinely what you want, say so explicitly:
scms:
default:
kind: github
spec:
force: trueImportant | force: true means git push --force to the branch you named. Some targets, the shell
plugin in particular, commit every change in the working directory, so what gets force-pushed may be
more than you expected. |
Rate limiting
Updatecli appears to hang
Usually it is waiting out a GitHub rate limit, on purpose. When the remaining credit reaches zero, Updatecli sleeps until the window resets rather than failing:
GitHub API rate limit reached, on hold for 45 minute(s) until 2026-07-30 11:15:00 UTC. The process will resume automatically.There is nothing to fix in the run, it resumes by itself. To avoid the wait, reduce how many API
calls the manifest makes, or authenticate with a token that has a larger allowance. Run with
--debug to watch the credit drain: GitHub API credit used 1, remaining 4998 (reset at …).
API rate limit already exceeded
API rate limit already exceeded
API rate limit exceeded, final attempt failedThe first appears when a call starts with no credit left; Updatecli retries. The second means the retries ran out. An unauthenticated run hits this quickly, GitHub’s anonymous allowance is far smaller than an authenticated one, so setting a token is usually the whole fix.
Tip | Docker Hub has its own, unrelated limits, with their own symptoms. See the "Docker Hub rate limit" page. |
Git push and branches
force push needed, use scm parameter "force" to true
force push needed, use scm parameter "force" to trueThe remote branch has commits that the local one does not, so a fast-forward push is impossible. This normally means something else moved the branch (a previous Updatecli run, or a human).
Setting force: true on the scm lets Updatecli overwrite it. That is safe on a generated working
branch and destructive anywhere else, so check which branch is being pushed before reaching for the
flag.
not pushing from a branch
HEAD is detached, so there is no branch name to push. Usually a checkout by commit hash or tag
rather than by branch. Set branch on the scm.
working directory has uncommitted changes
Squashing refuses to run while the working tree is dirty, because the result would silently include whatever was lying around. Commit or clean first.
Nothing to squash
feature branch updatecli_main_xxx is at same commit as base branch main, nothing to squash
feature branch updatecli_main_xxx is not ahead of base branch main
no changes found between main and updatecli_main_xxxAll three mean the working branch holds no new work relative to the base branch. That is the expected outcome when a run changed nothing, not a failure to investigate.
Commit signing
failed to load GPG key: ...
GPG key does not have a private key for signing
GPG key is still encrypted after decryption attemptfailed to load GPG keyThe armored key could not be parsed. Check that the whole block was passed, including the
-----BEGIN PGP PRIVATE KEY BLOCK-----header and footer, and that a multi-line value survived however you injected it.GPG key does not have a private key for signingA public key was supplied. Signing needs the private half.
GPG key is still encrypted after decryption attemptThe passphrase was missing or wrong.
The key and passphrase belong under the scm spec:
scms:
default:
kind: github
spec:
gpg:
signingkey: |
-----BEGIN PGP PRIVATE KEY BLOCK-----
...
passphrase: '{{ requiredEnv "GPG_PASSPHRASE" }}'Manifest validation
These are reported before anything runs, so a diff finds all of them.
the specified sourceid "…" for target "…" does not exist
The target names a source that is not defined in the same manifest. Source and target identifiers are the YAML keys, and they are case-sensitive.
empty 'sourceid' for target "…"
The target has no sourceid and the manifest defines more than one source, so Updatecli cannot
guess which value to use. With exactly one source it is inferred silently; the error only appears
once a second source exists.
Name it explicitly, or set disablesourceinput: true on targets that need no source value.
target "…" has undefined conditionids
A deprecated conditionids entry names a condition that does not exist. See
"Deprecations", conditionids is superseded by
dependson.
… key "…" contains forbidden go template instruction
sources key "{{ .name }}" contains forbidden go template instructionTemplating is allowed in values, not in the identifiers a stage is keyed by. Updatecli needs stable
identifiers to resolve sourceid and dependson before templating runs. Rename the key to a literal.
dependency loop detected
Two or more stages depend on each other, directly or through a chain. Also possible:
no valid depends_on value, when a dependson entry names something that does not exist.
The "Execution order" page explains how the graph is built.
pipeline "…" requires Updatecli version greater than "…"
The manifest sets a minimum version higher than the binary in use. The pipeline is skipped, not failed, so a run can report success while doing nothing. Upgrade Updatecli, or lower the requirement if it is no longer accurate.
Version filtering
The most common source of "it found nothing", and the messages are terse enough to be misleading.
no version found
versions list empty
no version found matching pattern "..."
no valid semantic version found
no valid date found
no valid PEP 440 version found
wrong semantic versioning constraint "..."
unsupported version kind "..."
unsupported version kind "..." with pattern "..."versions list emptyThe lookup itself returned nothing, the repository, registry, or API has no versions at all. The filter is not the problem; the query is. Check the repository name and credentials first.
no version found matching pattern "…"Versions were found, and none matched. Print the raw list with
--debugbefore adjusting the pattern.no valid semantic version foundThe versions exist but are not semver, while the filter is
kind: semver. Tags like2024-06-01orrelease-7needkind: regexorkind: timeinstead.wrong semantic versioning constraint "…"The constraint expression itself is malformed,
~>2.0rather than~2.0, for example.unsupported version kind "…"A typo in
kind. The accepted values are on the "Version Filtering" page.
Important | A version filter is a subset check, not an ordering. kind: latest returns what the
upstream considers latest, it does not sort the list and pick the highest. When the newest tag is not
the one you expect, that distinction is usually why. |
Nothing happened
The run finished, reported success, and opened nothing. In order of likelihood:
Nothing needed changing. The normal outcome. Targets report as unchanged and no action is created.
A condition did not pass. Conditions gate the targets of their pipeline; when one fails, those targets are skipped. The log names the condition.
Committing or pushing was switched off.
--commit=falseand--push=falseonupdatecli pipeline apply, or runningpipeline diff, which sets both.The pipeline was filtered out.
--pipeline-idsand--labelsnarrow a run; anything not selected never executes.The manifest requires a newer Updatecli. Reported as a skip, as described above.
Run with --debug (the per-target result says which of these applied).
Note | An action whose targets all reported unchanged is not simply skipped. Updatecli still looks for a pull request opened by an earlier run, so an update that has become obsolete is reported rather than left dangling. See the "Action" page. |
Still stuck?
Confirm the behaviour is not a documented deprecation - Deprecations.
Check whether the feature needs
--experimental- Experimental features.Ask on one of the channels listed on the support page, including the manifest and the
--debugoutput.