{"record":{"id":"3415ac2439d3282c","repo":"hashicorp/nomad","slug":"failed-to-stat-intro-token-file-w","errorCode":null,"errorMessage":"failed to stat intro token file: %w","messagePattern":"failed to stat intro token file: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"command/agent/agent.go","lineNumber":872,"sourceCode":"\t}\n\n\treturn nil\n}\n\n// readIntroTokenFile attempts to read the intro token from the file system.\nfunc (a *Agent) readIntroTokenFile(cfg *clientconfig.Config) error {\n\n\trootFile, err := os.OpenInRoot(cfg.StateDir, \"intro_token.jwt\")\n\tif err != nil {\n\t\tif os.IsNotExist(err) {\n\t\t\treturn nil\n\t\t}\n\t\treturn err\n\t}\n\n\tfileStat, err := rootFile.Stat()\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to stat intro token file: %w\", err)\n\t}\n\n\t// If the file exists and is a file, attempt to read the contents and set\n\t// the intro token. Any error is logged for the operator to investigate but\n\t// does not block the agent from starting.\n\tif fileStat.IsDir() {\n\t\treturn fmt.Errorf(\"intro token file is a directory\")\n\t}\n\n\tcontent, err := helper.ReadFileContent(rootFile)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to read intro token file: %w\", err)\n\t}\n\n\tcfg.IntroToken = strings.TrimSpace(string(content))\n\treturn nil\n}\n","sourceCodeStart":854,"sourceCodeEnd":890,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/command/agent/agent.go#L854-L890","documentation":"readIntroTokenFile opens the configured introduction-token file and calls Stat() on it. If Stat fails (typically because the file does not exist, or permissions deny the stat), the underlying error is wrapped as 'failed to stat intro token file'. The caller propagates this instead of loading an intro token.","triggerScenarios":"client.intro_token_file (the path opened as rootFile) pointing to a nonexistent path, a path in a directory the agent user cannot traverse, or a broken symlink, when finalizeClientConfig calls readIntroTokenFile during startup/reload.","commonSituations":"Typos in the token file path; file created by root with 0600 while Nomad runs as the nomad user; secret-management provisioning that deleted the file before agent start; containers missing a mounted secret volume.","solutions":["Verify the path in intro_token_file exists: ls -l <path>.","Fix file permissions/ownership so the Nomad agent user can stat and read it (chown nomad:nomad; chmod 600).","Ensure the token file is provisioned before the agent starts (init container/systemd ordering, volume mounts)."],"exampleFix":"// before (hcl)\nclient { intro_token_file = \"/etc/nomad/tokens/intro\" } // file absent\n// after (shell)\ninstall -o nomad -g nomad -m 600 /dev/null /etc/nomad/tokens/intro && echo \"$TOKEN\" > /etc/nomad/tokens/intro\n// client { intro_token_file = \"/etc/nomad/tokens/intro\" }","handlingStrategy":"validation","validationCode":"path := cfg.Client.IntroTokenFile\nif _, err := os.Stat(path); err != nil {\n  return fmt.Errorf(\"intro token file %q not statable before agent start: %w\", path, err)\n}","typeGuard":null,"tryCatchPattern":"if err := readIntroTokenFile(cfg, path); err != nil {\n  var pe *fs.PathError\n  if errors.As(err, &pe) {\n    log.Errorf(\"intro token file %s unavailable: %v\", path, pe)\n  }\n  return err\n}","preventionTips":["Provision the token file (with correct ownership) before the agent starts.","Use systemd/init ordering or entrypoint scripts to guarantee file presence.","Mount secrets as files, not directories, and reference the file path."],"tags":["filesystem","nomad","permissions"],"backgroundTag":"file-not-found","analyzedSha":"482b49bf1aec006f089bcfc7e632d8f6ac303e5e","analyzedAt":"2026-09-04T07:54:14.808Z","contentChangedAt":"2026-09-04T07:54:14.808Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}