{"record":{"id":"1fad225d7d705aba","repo":"slimtoolkit/slim","slug":"root-q-is-not-absolute","errorCode":null,"errorMessage":"root %q is not absolute","messagePattern":"root %q is not absolute","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/app/master/probe/http/internal/fastcgi.go","lineNumber":141,"sourceCode":"// buildEnv returns a set of CGI environment variables for the request.\nfunc (t FastCGITransport) buildEnv(r *http.Request) (map[string]string, error) {\n\n\t// Separate remote IP and port; more lenient than net.SplitHostPort\n\tvar ip, port string\n\tif idx := strings.LastIndex(r.RemoteAddr, \":\"); idx > -1 {\n\t\tip = r.RemoteAddr[:idx]\n\t\tport = r.RemoteAddr[idx+1:]\n\t} else {\n\t\tip = r.RemoteAddr\n\t}\n\n\t// Remove [] from IPv6 addresses\n\tip = strings.Replace(ip, \"[\", \"\", 1)\n\tip = strings.Replace(ip, \"]\", \"\", 1)\n\n\t// make sure file root is absolute\n\tif !path.IsAbs(t.Root) {\n\t\treturn nil, fmt.Errorf(\"root %q is not absolute\", t.Root)\n\t}\n\troot := t.Root\n\n\tfpath := r.URL.Path\n\tscriptName := fpath\n\n\tdocURI := fpath\n\t// split \"actual path\" from \"path info\" if configured\n\tvar pathInfo string\n\tif splitPos := t.splitPos(fpath); splitPos > -1 {\n\t\tdocURI = fpath[:splitPos]\n\t\tpathInfo = fpath[splitPos:]\n\n\t\t// Strip PATH_INFO from SCRIPT_NAME\n\t\tscriptName = strings.TrimSuffix(scriptName, pathInfo)\n\t}\n\n\t// SCRIPT_FILENAME is the absolute path of SCRIPT_NAME","sourceCodeStart":123,"sourceCodeEnd":159,"githubUrl":"https://github.com/slimtoolkit/slim/blob/81940d17fa112cc678e32209214bcb2355cb3004/pkg/app/master/probe/http/internal/fastcgi.go#L123-L159","documentation":"The fastcgi RoundTrip transport requires the FastCGI application's document root (t.Root) to be an absolute filesystem path because the FastCGI protocol sends the ROOT document path to the backend. Before dialing the backend, buildEnv strips IPv6 brackets from the host and validates that Root starts with '/'; if it does not, the request cannot be converted into a valid FastCGI PARAMS block and this error is returned to the caller of RoundTrip.","triggerScenarios":"Calling http.Client.Do (or Transport.RoundTrip) on a client whose Transport is the fastcgi handler transport with a target whose Root field was set to a relative path (e.g. \"www\", \"./public\", or an empty string) instead of an absolute path like \"/var/www\".","commonSituations":"Configuring the FastCGI target root from a config flag or environment variable that holds a relative directory; forgetting to prefix the root with '/' when hand-building the fastcgi handler; passing a URL-style path (\"/app\" vs actual filesystem path) or leaving Root unset (empty string is not absolute).","solutions":["Set t.Root to an absolute filesystem path (must start with '/'), e.g. \"/srv/www/current/public\".","If the root comes from config/env, convert it with filepath.Abs before constructing the transport.","Verify the value is non-empty; an empty Root is not absolute and fails the same check.","On macOS/Windows-style inputs, ensure separators and drive prefixes are converted to the container/OS absolute form before use."],"exampleFix":"// before\ntransport := &fastcgi.Transport{Root: \"public\", ...}\n// after\nroot, err := filepath.Abs(\"public\")\nif err != nil {\n    return err\n}\ntransport := &fastcgi.Transport{Root: root, ...}","handlingStrategy":"validation","validationCode":"if !filepath.IsAbs(root) || root == \"\" {\n    abs, err := filepath.Abs(root)\n    if err != nil {\n        return fmt.Errorf(\"cannot resolve fastcgi root %q: %w\", root, err)\n    }\n    root = abs\n}\ntransport := &fastcgi.Transport{Root: root, ...}","typeGuard":"func isAbsoluteRoot(root string) bool {\n    return root != \"\" && filepath.IsAbs(root)\n}","tryCatchPattern":"resp, err := client.Do(req)\nif err != nil {\n    if strings.Contains(err.Error(), \"is not absolute\") {\n        return nil, fmt.Errorf(\"fix fastcgi transport Root to an absolute path: %w\", err)\n    }\n    return nil, err\n}","preventionTips":["Always build the transport Root with filepath.Abs or an absolute constant","Validate configured root paths at startup, before any requests are made","Never leave Root empty; empty strings fail the IsAbs check"],"tags":["fastcgi","path-validation","http-transport","configuration"],"backgroundTag":"path-not-absolute","analyzedSha":"81940d17fa112cc678e32209214bcb2355cb3004","analyzedAt":"2026-08-31T23:06:12.682Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}