{"record":{"id":"c134c224d6992591","repo":"gravitational/teleport","slug":"updater-config-file-not-found","errorCode":null,"errorMessage":"updater config file not found","messagePattern":"updater config file not found","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"lib/autoupdate/agent/integrations.go","lineNumber":37,"sourceCode":"package agent\n\nimport (\n\t\"context\"\n\t\"errors\"\n\t\"io/fs\"\n\t\"log/slog\"\n\t\"os\"\n\t\"path/filepath\"\n\n\t\"github.com/google/uuid\"\n\t\"github.com/gravitational/trace\"\n\n\t\"github.com/gravitational/teleport/api/types\"\n)\n\nvar (\n\t// ErrConfigNotFound is returned by HellorUpdaterInfo when the updater config file cannot be found.\n\tErrConfigNotFound = errors.New(\"updater config file not found\")\n\n\t// ErrUnstableExecutable is returned by StableExecutable when no stable path can be found.\n\tErrUnstableExecutable = errors.New(\"executable has unstable path\")\n)\n\nconst updateConfigFileEnvVar = \"TELEPORT_UPDATE_CONFIG_FILE\"\n\n// IsManagedByUpdater returns true if the local Teleport binary is managed by teleport-update.\n// Note that true may be returned even if auto-updates is disabled or the version is pinned.\n// The binary is considered managed if it lives under /opt/teleport, but not within the package\n// path at /opt/teleport/system.\nfunc IsManagedByUpdater() (bool, error) {\n\tsystemd, err := hasSystemD()\n\tif err != nil {\n\t\treturn false, trace.Wrap(err)\n\t}\n\tif !systemd {\n\t\treturn false, nil","sourceCodeStart":19,"sourceCodeEnd":55,"githubUrl":"https://github.com/gravitational/teleport/blob/1283425b60ec5f60d509ba4c791183d452923ff7/lib/autoupdate/agent/integrations.go#L19-L55","documentation":"ErrConfigNotFound is the sentinel returned by findConfigFile (and consumers like HellorUpdaterInfo/StableExecutable paths) when the Teleport updater's update.yaml cannot be located. findConfigFile derives the config location from the running executable's path: it must live under an installation whose binary is four directories below the install root (i.e. under .../versions/... of a managed install). If TELEPORT_UPDATE_CONFIG_FILE is unset and the binary layout does not match a managed install, no update.yaml path exists and this error is wrapped.","triggerScenarios":"Calling ReadHelloUpdaterInfo (or anything calling findConfigFile) when: (1) TELEPORT_UPDATE_CONFIG_FILE is not set, (2) os.Executable() is not under a .../<parent>/versions/<dir>/ layout matching findParentMatching(path, versionsDirName, 4), so the function returns trace.Wrap(ErrConfigNotFound) at integrations.go:158.","commonSituations":"Kubernetes (kube controller) upgraders on older chart versions where no update.yaml is deployed — expected and handled at lib/service/service.go:1456; Teleport installed from a tarball or manually placed outside /opt/teleport's versions layout; custom install paths that break the versions-dir convention.","solutions":["If this is a Kubernetes upgrader, treat it as expected: the service skips updater info when errors.Is(err, ErrConfigNotFound) — verify you are on a chart version that does this.","Set TELEPORT_UPDATE_CONFIG_FILE to the absolute path of update.yaml if your install layout is non-standard.","Reinstall via an updater-managed layout (binary under <install>/versions/...) so findParentMatching can locate the config.","Check that the running binary path is the managed install path, not a copied/symlinked binary elsewhere."],"exampleFix":"// before: binary outside managed layout, no config found\n$ TELEPORT_UPDATE_CONFIG_FILE= ./teleport version\n// after: point at the config explicitly\n$ export TELEPORT_UPDATE_CONFIG_FILE=/opt/teleport/update.yaml","handlingStrategy":"type-guard","validationCode":"// Detect the condition before it is wrapped:\n_, err := os.Stat(\"/opt/teleport/update.yaml\")\nhasConfig := err == nil\n// Or set the env var for non-standard layouts:\nos.Setenv(\"TELEPORT_UPDATE_CONFIG_FILE\", \"/path/to/update.yaml\")","typeGuard":"func isConfigNotFound(err error) bool { return errors.Is(err, autoupdate.ErrConfigNotFound) }","tryCatchPattern":"info, err := autoupdate.ReadHelloUpdaterInfo(ctx, log, hostUUID)\nif errors.Is(err, autoupdate.ErrConfigNotFound) {\n    // no updater config: treat as unmanaged (see lib/service/service.go:1456)\n    return hello, nil\n} else if err != nil {\n    return trace.Wrap(err)\n}","preventionTips":["Install Teleport into the managed layout so update.yaml sits at <install>/update.yaml.","Set TELEPORT_UPDATE_CONFIG_FILE when using custom install paths.","Check errors.Is(err, ErrConfigNotFound) explicitly rather than string matching."],"tags":["autoupdate","config","go","sentinel-error"],"backgroundTag":"config-file-not-found","analyzedSha":"1283425b60ec5f60d509ba4c791183d452923ff7","analyzedAt":"2026-09-02T04:06:41.601Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}