{"record":{"id":"4af58f8b47729d42","repo":"caddyserver/caddy","slug":"reading-config-from-stdin-v","errorCode":null,"errorMessage":"reading config from stdin: %v","messagePattern":"reading config from stdin: (.+?)","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/main.go","lineNumber":166,"sourceCode":"\t// just so we don't have to check for nil\n\tif logger == nil {\n\t\tlogger = zap.NewNop()\n\t}\n\n\t// specifying an adapter without a config file is ambiguous\n\tif adapterName != \"\" && configFile == \"\" {\n\t\treturn nil, \"\", \"\", fmt.Errorf(\"cannot adapt config without config file (use --config)\")\n\t}\n\n\t// load initial config and adapter\n\tvar config []byte\n\tvar cfgAdapter caddyconfig.Adapter\n\tvar err error\n\tif configFile != \"\" {\n\t\tif configFile == \"-\" {\n\t\t\tconfig, err = io.ReadAll(os.Stdin)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, \"\", \"\", fmt.Errorf(\"reading config from stdin: %v\", err)\n\t\t\t}\n\t\t\tlogger.Info(\"using config from stdin\")\n\t\t} else {\n\t\t\tconfig, err = os.ReadFile(configFile)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, \"\", \"\", fmt.Errorf(\"reading config from file: %v\", err)\n\t\t\t}\n\t\t\tlogger.Info(\"using config from file\", zap.String(\"file\", configFile))\n\t\t}\n\t} else if adapterName == \"\" {\n\t\t// if the Caddyfile adapter is plugged in, we can try using an\n\t\t// adjacent Caddyfile by default\n\t\tcfgAdapter = caddyconfig.GetAdapter(\"caddyfile\")\n\t\tif cfgAdapter != nil {\n\t\t\tconfig, err = os.ReadFile(\"Caddyfile\")\n\t\t\tif errors.Is(err, fs.ErrNotExist) {\n\t\t\t\t// okay, no default Caddyfile; pretend like this never happened\n\t\t\t\tcfgAdapter = nil","sourceCodeStart":148,"sourceCodeEnd":184,"githubUrl":"https://github.com/caddyserver/caddy/blob/50e54ee279aa1e504fe218ca49ab6ae16c100410/cmd/main.go#L148-L184","documentation":"The special config path '-' makes Caddy read the config from stdin, and this wraps an io.ReadAll(os.Stdin) failure. The pipe/stdin could not be read — broken pipe, closed stdin, or an OS-level read error.","triggerScenarios":"Running 'caddy run --config -' with stdin closed (no redirect in a cron/systemd unit), or an upstream producer of the pipe exiting mid-write.","commonSituations":"Systemd units without StandardInput=pipe; scripts where the generating command failed so the pipe delivered EOF/error; interactive shells where the command appears to hang then error.","solutions":["Ensure something feeds stdin: cat config | caddy run --config -","In service units, set StandardInput=file:/path or just use --config with a real path","Verify the producer of the pipe succeeded before piping into caddy"],"exampleFix":"# before (systemd unit, stdin not wired)\nExecStart=/usr/bin/caddy run --config -\n\n# after\nExecStart=/usr/bin/caddy run --config /etc/caddy/Caddyfile --adapter caddyfile","handlingStrategy":"validation","validationCode":"# Confirm stdin is wired before using '--config -':\nif [ -t 0 ]; then echo \"refusing to read config from a terminal\" >&2; exit 1; fi\ncat Caddyfile | caddy adapt --config - --adapter caddyfile","typeGuard":null,"tryCatchPattern":null,"preventionTips":["In systemd units, use StandardInput=file: or real file paths","Guard scripts with [ -t 0 ] so a missing pipe fails fast"],"tags":["cli","configuration","stdin","io"],"backgroundTag":null,"analyzedSha":"50e54ee279aa1e504fe218ca49ab6ae16c100410","analyzedAt":"2026-08-15T09:20:21.641Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}