{"record":{"id":"7a6de40457aa58f6","repo":"caddyserver/caddy","slug":"setting-up-subroutes-v","errorCode":null,"errorMessage":"setting up subroutes: %v","messagePattern":"setting up subroutes: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"modules/caddyhttp/subroute.go","lineNumber":60,"sourceCode":"\t// If the primary routes return an error, error handling\n\t// can be promoted to this configuration instead.\n\tErrors *HTTPErrorConfig `json:\"errors,omitempty\"`\n}\n\n// CaddyModule returns the Caddy module information.\nfunc (Subroute) CaddyModule() caddy.ModuleInfo {\n\treturn caddy.ModuleInfo{\n\t\tID:  \"http.handlers.subroute\",\n\t\tNew: func() caddy.Module { return new(Subroute) },\n\t}\n}\n\n// Provision sets up subrouting.\nfunc (sr *Subroute) Provision(ctx caddy.Context) error {\n\tif sr.Routes != nil {\n\t\terr := sr.Routes.Provision(ctx)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"setting up subroutes: %v\", err)\n\t\t}\n\t\tif sr.Errors != nil {\n\t\t\terr := sr.Errors.Routes.Provision(ctx)\n\t\t\tif err != nil {\n\t\t\t\treturn fmt.Errorf(\"setting up error subroutes: %v\", err)\n\t\t\t}\n\t\t}\n\t}\n\treturn nil\n}\n\nfunc (sr *Subroute) ServeHTTP(w http.ResponseWriter, r *http.Request, next Handler) error {\n\tsubroute := sr.Routes.Compile(next)\n\terr := subroute.ServeHTTP(w, r)\n\tif err != nil && sr.Errors != nil {\n\t\tr = sr.Errors.WithError(r, err)\n\t\terrRoute := sr.Errors.Routes.Compile(next)\n\t\treturn errRoute.ServeHTTP(w, r)","sourceCodeStart":42,"sourceCodeEnd":78,"githubUrl":"https://github.com/caddyserver/caddy/blob/50e54ee279aa1e504fe218ca49ab6ae16c100410/modules/caddyhttp/subroute.go#L42-L78","documentation":"Returned by Subroute.Provision when provisioning the route list inside a subroute handler fails. The wrapped error comes from RouteList.Provision, which provisions each route's matcher sets and handlers, so the real cause is in the nested error string.","triggerScenarios":"A JSON config containing a 'http.handlers.subroute' module whose 'routes' array references an unknown module ID, a matcher module that fails provisioning, or a handler whose Provision returns an error. Occurs at config load/adapt time, before serving.","commonSituations":"Typos in module names inside a subroute, referencing a handler from a non-standard build not compiled in, malformed matcher syntax in imported Caddyfile snippets, or version mismatches after upgrading Caddy where a module changed its namespace.","solutions":["Read the wrapped error after the colon; it names the actual failing route/module","Validate module IDs against the running binary with `caddy list-modules`","Fix or remove the offending route in the subroute's routes array","If using a custom build, rebuild with the plugin that provides the missing module"],"exampleFix":"// before\n{\n  \"handler\": \"subroute\",\n  \"routes\": [\n    { \"handle\": [{ \"handler\": \"rewrit\", \"path\": \"/new\" }] }\n  ]\n}\n\n// after\n{\n  \"handler\": \"subroute\",\n  \"routes\": [\n    { \"handle\": [{ \"handler\": \"rewrite\", \"path\": \"/new\" }] }\n  ]\n}","handlingStrategy":"validation","validationCode":"# validate config (and subroute module ids) before deploy\ncaddy validate --config Caddyfile --adapter caddyfile\ncaddy list-modules | grep -E '^http\\.(handlers|matchers)\\.' >/dev/null || echo 'unexpected module set'","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Run `caddy validate` in CI for every config change","Pin plugin sets with xcaddy and a checked-in build recipe","Prefer `caddy adapt` output review when hand-editing subroute JSON"],"tags":["caddy","subroute","provisioning","configuration"],"backgroundTag":null,"analyzedSha":"50e54ee279aa1e504fe218ca49ab6ae16c100410","analyzedAt":"2026-08-15T09:20:21.641Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}