{"record":{"id":"44979a42d53527f5","repo":"caddyserver/caddy","slug":"preparing-ask-endpoint-v-44979a","errorCode":null,"errorMessage":"preparing 'ask' endpoint: %v","messagePattern":"preparing 'ask' endpoint: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"modules/caddytls/tls.go","lineNumber":325,"sourceCode":"\t\t}\n\t\terr = t.Automation.defaultInternalAutomationPolicy.Provision(t)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"provisioning default internal automation policy: %v\", err)\n\t\t}\n\t\tbreak\n\t}\n\tfor i, ap := range t.Automation.Policies {\n\t\terr := ap.Provision(t)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"provisioning automation policy %d: %v\", i, err)\n\t\t}\n\t}\n\n\t// run replacer on ask URL (for environment variables) -- return errors to prevent surprises (#5036)\n\tif t.Automation != nil && t.Automation.OnDemand != nil && t.Automation.OnDemand.Ask != \"\" {\n\t\tt.Automation.OnDemand.Ask, err = repl.ReplaceOrErr(t.Automation.OnDemand.Ask, true, true)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"preparing 'ask' endpoint: %v\", err)\n\t\t}\n\t\tperm := PermissionByHTTP{\n\t\t\tEndpoint: t.Automation.OnDemand.Ask,\n\t\t}\n\t\tif err := perm.Provision(ctx); err != nil {\n\t\t\treturn fmt.Errorf(\"provisioning 'ask' module: %v\", err)\n\t\t}\n\t\tt.Automation.OnDemand.permission = perm\n\t}\n\n\t// session ticket ephemeral keys (STEK) service and provider\n\tif t.SessionTickets != nil {\n\t\terr := t.SessionTickets.provision(ctx)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"provisioning session tickets configuration: %v\", err)\n\t\t}\n\t}\n","sourceCodeStart":307,"sourceCodeEnd":343,"githubUrl":"https://github.com/caddyserver/caddy/blob/50e54ee279aa1e504fe218ca49ab6ae16c100410/modules/caddytls/tls.go#L307-L343","documentation":"The deprecated on_demand 'ask' URL is run through the placeholder replacer (repl.ReplaceOrErr with error-on-failure) so environment variables like {$ASK_URL} can be substituted; per issue #5036 a silently-unresolved placeholder would surprise users, so failure is fatal. This error means the ask value contained a placeholder that could not be resolved (missing env var) — the empty string replacement was rejected.","triggerScenarios":"on_demand.ask = \"{$ON_DEMAND_ASK}\" but the ON_DEMAND_ASK environment variable is not set in Caddy's process environment; or a malformed placeholder syntax that the replacer treats as an error under ReplaceOrErr's strict mode.","commonSituations":"Deploying with systemd/container where the env var is defined in dev but absent in prod; renaming the variable; running under a service manager that strips environment.","solutions":["Export the environment variable before starting Caddy (systemd Environment=, docker -e, .env source)","Or replace the placeholder with a literal URL if the value is static","Verify with 'caddy environ' or 'systemctl show caddy -p Environment' that the variable is present"],"exampleFix":"# before\n\"on_demand\": {\"ask\": \"{$ON_DEMAND_ASK}\"}  # env var unset -> error\n# after\n$ export ON_DEMAND_ASK=http://localhost:5555/check\n$ caddy run --config Caddyfile","handlingStrategy":"validation","validationCode":"endpoint := os.Getenv(\"ON_DEMAND_ASK\")\nif endpoint == \"\" {\n\treturn fmt.Errorf(\"ON_DEMAND_ASK must be set; it is used in the config\")\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Declare all env vars referenced by config in the service unit/container spec","List required env vars in deployment docs and check them with a pre-start script"],"tags":["caddy","tls","on-demand","placeholders","environment-variables"],"backgroundTag":null,"analyzedSha":"50e54ee279aa1e504fe218ca49ab6ae16c100410","analyzedAt":"2026-08-15T09:20:21.641Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}