{"record":{"id":"9b043a88ea976353","repo":"cli/cli","slug":"already-up-to-date","errorCode":null,"errorMessage":"already up to date","messagePattern":"already up to date","errorType":"exception","errorClass":"upToDateError","httpStatus":null,"severity":"info","filePath":"pkg/cmd/extension/manager.go","lineNumber":456,"sourceCode":"\t}\n\n\tscopedClient := m.gitClient.ForRepo(targetDir)\n\terr = scopedClient.CheckoutBranch(commitSHA)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tpinPath := filepath.Join(targetDir, fmt.Sprintf(\".pin-%s\", commitSHA))\n\tf, err := os.OpenFile(pinPath, os.O_WRONLY|os.O_CREATE, 0600)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to create pin file in directory: %w\", err)\n\t}\n\treturn f.Close()\n}\n\nvar pinnedExtensionUpgradeError = errors.New(\"pinned extensions can not be upgraded\")\nvar localExtensionUpgradeError = errors.New(\"local extensions can not be upgraded\")\nvar upToDateError = errors.New(\"already up to date\")\nvar noExtensionsInstalledError = errors.New(\"no extensions installed\")\n\nfunc (m *Manager) Upgrade(name string, force bool) error {\n\t// Fetch metadata during list only when upgrading all extensions.\n\t// This is a performance improvement so that we don't make a\n\t// bunch of unnecessary network requests when trying to upgrade a single extension.\n\tfetchMetadata := name == \"\"\n\texts, _ := m.list(fetchMetadata)\n\tif len(exts) == 0 {\n\t\treturn noExtensionsInstalledError\n\t}\n\tif name == \"\" {\n\t\treturn m.upgradeExtensions(exts, force)\n\t}\n\tfor _, f := range exts {\n\t\tif f.Name() != name {\n\t\t\tcontinue\n\t\t}","sourceCodeStart":438,"sourceCodeEnd":474,"githubUrl":"https://github.com/cli/cli/blob/0eeec0b92edbe70199f9768522f831d3534f41ad/pkg/cmd/extension/manager.go#L438-L474","documentation":"Defined as the package-level sentinel upToDateError and returned by Manager.upgradeExtension when the extension is not pinned/local and its currently installed version already matches the latest available version (UpdateAvailable() false). It signals a no-op rather than a failure; when upgrading all extensions, gh catches it and prints 'already up to date' per extension instead of failing, but when you upgrade a single named extension the error surfaces to the command and exits nonzero.","triggerScenarios":"Running `gh extension upgrade <name>` when the local commit/semantic version equals the remote HEAD/latest release. In the upgrade-all path (name == \"\"), the error is detected via errors.Is and printed as an informational line; in the single-extension path it propagates.","commonSituations":"Idempotent cron/CI jobs that upgrade on a schedule and hit the sentinel on every run after the first; users manually upgrading right after installing; stale local metadata making gh believe it is current when a newer version exists (fix by re-listing with network).","solutions":["Treat it as success in scripts: `gh extension upgrade <name> || [ $? -eq 1 ]`-style guards or match the 'already up to date' message.","If you expected a newer version, refresh metadata: `gh extension list` triggers a fetch, or reinstall with `gh extension install <owner>/<gh-name> --force`.","For scheduled upgrades prefer `gh extension upgrade --all`, which reports up-to-date extensions without failing."],"exampleFix":"# before (cron)\ngh extension upgrade gh-changelog || exit 1   # fails when current\n\n# after\ngh extension upgrade gh-changelog || grep -q 'already up to date' /dev/stdin || true\n# simpler: use bulk mode which tolerates it\ngh extension upgrade --all","handlingStrategy":"try-catch","validationCode":"# bash: compare current vs latest before upgrading (non-TTY tolerant)\nver=$(gh extension list --json name,version,latestVersion \\\n  -q \".[] | select(.name==\\\"gh-changelog\\\") | if .version == .latestVersion then \\\"current\\\" else \\\"stale\\\" end\")\n[[ \"$ver\" == current ]] && { echo 'already current'; exit 0; }\ngh extension upgrade gh-changelog","typeGuard":null,"tryCatchPattern":"out=$(gh extension upgrade gh-changelog 2>&1); rc=$?\nif [[ $rc -eq 0 ]]; then echo upgraded\nelif [[ \"$out\" == *'already up to date'* ]]; then echo 'no-op: current'; exit 0\nelse echo \"$out\" >&2; exit $rc\nfi","preventionTips":["Use `gh extension upgrade` (all) in schedulers; it reports up-to-date items without failing.","Treat 'already up to date' as exit-success in idempotent automation."],"tags":["cli","extension","upgrade","no-op"],"backgroundTag":null,"analyzedSha":"0eeec0b92edbe70199f9768522f831d3534f41ad","analyzedAt":"2026-08-15T12:31:05.478Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}