{"record":{"id":"2c8b8e1e588e280c","repo":"cloudflare/cloudflared","slug":"configuration-file-s-must-contain-entries-for-the","errorCode":null,"errorMessage":"configuration file %s must contain entries for the tunnel to run and its associated credentials (tunnel: TUNNEL-UUID, credentials-file: CREDENTIALS-FILE)","messagePattern":"configuration file (.+?) must contain entries for the tunnel to run and its associated credentials \\(tunnel: TUNNEL-UUID, credentials-file: CREDENTIALS-FILE\\)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/cloudflared/linux_service.go","lineNumber":332,"sourceCode":"}\n\nfunc buildArgsForConfig(c *cli.Context, log *zerolog.Logger) ([]string, error) {\n\tif err := ensureConfigDirExists(serviceConfigDir); err != nil {\n\t\treturn nil, err\n\t}\n\n\tsrc, _, err := config.ReadConfigFile(c, log)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// can't use context because this command doesn't define \"credentials-file\" flag\n\tconfigPresent := func(s string) bool {\n\t\tval, err := src.String(s)\n\t\treturn err == nil && val != \"\"\n\t}\n\tif src.TunnelID == \"\" || !configPresent(tunnel.CredFileFlag) {\n\t\treturn nil, fmt.Errorf(\"configuration file %s must contain entries for the tunnel to run and its associated credentials (tunnel: TUNNEL-UUID, credentials-file: CREDENTIALS-FILE)\", src.Source())\n\t}\n\tif src.Source() != serviceConfigPath {\n\t\tif exists, err := config.FileExists(serviceConfigPath); err != nil || exists {\n\t\t\treturn nil, fmt.Errorf(\"possible conflicting configuration in %[1]s and %[2]s. Either remove %[2]s or run `cloudflared --config %[2]s service install`\", src.Source(), serviceConfigPath)\n\t\t}\n\n\t\tif err := copyFile(src.Source(), serviceConfigPath); err != nil {\n\t\t\treturn nil, fmt.Errorf(\"failed to copy %s to %s: %w\", src.Source(), serviceConfigPath, err)\n\t\t}\n\t}\n\n\treturn []string{\n\t\t\"--config\", \"/etc/cloudflared/config.yml\", \"tunnel\", \"run\",\n\t}, nil\n}\n\nfunc installSystemd(templateArgs *ServiceTemplateArgs, autoUpdate bool, log *zerolog.Logger) error {\n\tvar systemdTemplates []ServiceTemplate","sourceCodeStart":314,"sourceCodeEnd":350,"githubUrl":"https://github.com/cloudflare/cloudflared/blob/2253eeeb25a44a713a4b60b8ba1e1b3f377d1a0f/cmd/cloudflared/linux_service.go#L314-L350","documentation":"Thrown by buildArgsForConfig in cmd/cloudflared/linux_service.go when installing cloudflared as a Linux service. Before the service can run autonomously, the config file must name the tunnel (TunnelID) and its credentials file (credentials-file). If either entry is missing or empty, service installation is aborted because the systemd/OpenRC unit would launch a tunnel it cannot identify or authenticate.","triggerScenarios":"Running `cloudflared service install` where the effective config source (flag --config file or token-based config) has src.TunnelID == \"\" or no non-empty value for tunnel.CredFileFlag. Typical when the config file lacks `tunnel:` and/or `credentials-file:` keys, or only `ingress:` rules are present.","commonSituations":"Users write a config with only ingress rules and try to install it as a service; migrating from `cloudflared tunnel run` (flag-based) to service install without adding tunnel/credentials-file keys; copying an example config that omits credentials; using a remotely-managed tunnel token but an incomplete local config file.","solutions":["Add `tunnel: <TUNNEL-UUID>` and `credentials-file: /path/to/<UUID>.json` to the config file passed to `cloudflared service install`.","Alternatively install with a token: `cloudflared service install <TOKEN>` for remotely-managed tunnels.","Verify the config file being picked up (check the path in the error message) — use `cloudflared --config /path/config.yml tunnel ingress validate` to confirm entries parse.","Re-run `cloudflared --config /path/config.yml service install` after fixing the file."],"exampleFix":"// before: config.yml\n// ingress:\n//   - hostname: app.example.com\n//     service: http://localhost:8080\n\n// after: config.yml\n// tunnel: 6ff42ae2-765d-4adf-8336-94d036a6e840\n// credentials-file: /etc/cloudflared/6ff42ae2-765d-4adf-8336-94d036a6e840.json\n// ingress:\n//   - hostname: app.example.com\n//     service: http://localhost:8080","handlingStrategy":"validation","validationCode":"// Go: validate config before service install\ncfg, err := config.LoadConfig(configPath)\nif err != nil {\n    return err\n}\nif cfg.TunnelID == \"\" {\n    return fmt.Errorf(\"config %s is missing 'tunnel:' entry required for service install\", configPath)\n}\nif cfg.CredFileFlag == \"\" || !config.FileExists(cfg.CredFileFlag) {\n    return fmt.Errorf(\"config %s is missing a valid 'credentials-file:' entry\", configPath)\n}","typeGuard":null,"tryCatchPattern":"// Go\ncmd := exec.Command(\"cloudflared\", \"--config\", configPath, \"service\", \"install\")\nout, err := cmd.CombinedOutput()\nif err != nil && strings.Contains(string(out), \"must contain entries for the tunnel\") {\n    // add tunnel/credentials-file keys to the config or use token-based install\n    return fmt.Errorf(\"config incomplete for service install: %s\", out)\n}","preventionTips":["Always include both `tunnel:` and `credentials-file:` keys in any config destined for service install","Run `cloudflared tunnel ingress validate --config <file>` before installing the service","Prefer token-based installs (`cloudflared service install <TOKEN>`) for remotely-managed tunnels","Keep a canonical /etc/cloudflared/config.yml and edit it directly rather than passing ad-hoc configs"],"tags":["cli","configuration","service-install","tunnel"],"backgroundTag":"missing-required-config-field","analyzedSha":"2253eeeb25a44a713a4b60b8ba1e1b3f377d1a0f","analyzedAt":"2026-09-06T04:14:33.757Z","contentChangedAt":"2026-09-06T04:14:33.757Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}