{"record":{"id":"46f6a7588386fb9d","repo":"vxcontrol/pentagi","slug":"invalid-path-46f6a7","errorCode":null,"errorMessage":"invalid path","messagePattern":"invalid path","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"backend/pkg/resources/resources.go","lineNumber":158,"sourceCode":"\t}\n\tif len(trimmed) > MaxPathLength {\n\t\treturn \"\", fmt.Errorf(\"path exceeds maximum allowed length of %d characters\", MaxPathLength)\n\t}\n\n\tnormalized := strings.ReplaceAll(trimmed, \"\\\\\", \"/\")\n\tif strings.HasPrefix(normalized, \"/\") {\n\t\treturn \"\", fmt.Errorf(\"path must be relative\")\n\t}\n\tfor _, part := range strings.Split(normalized, \"/\") {\n\t\tif part == \"..\" {\n\t\t\treturn \"\", fmt.Errorf(\"path must not contain parent directory traversal\")\n\t\t}\n\t}\n\tcleaned := path.Clean(\"/\" + normalized)\n\t// Remove the leading \"/\" we added for Clean, making the path relative.\n\trel := strings.TrimPrefix(cleaned, \"/\")\n\tif rel == \"\" || rel == \".\" {\n\t\treturn \"\", fmt.Errorf(\"invalid path\")\n\t}\n\n\t// Validate every path component.\n\tparts := strings.Split(rel, \"/\")\n\tfor _, part := range parts {\n\t\tif err := validatePathComponent(part); err != nil {\n\t\t\treturn \"\", err\n\t\t}\n\t}\n\n\treturn rel, nil\n}\n\n// SanitizeResourceDir is like SanitizeResourcePath but also accepts an empty\n// string to mean \"root\". It returns \"\" for root, or a clean relative path.\nfunc SanitizeResourceDir(p string) (string, error) {\n\tif strings.TrimSpace(p) == \"\" {\n\t\treturn \"\", nil","sourceCodeStart":140,"sourceCodeEnd":176,"githubUrl":"https://github.com/vxcontrol/pentagi/blob/ea665308baaff015b226f308438a68d929d0f29b/backend/pkg/resources/resources.go#L140-L176","documentation":"SanitizeResourcePath returns this when, after cleaning, the resulting relative path is empty or '.' — i.e. the input named no actual file (it was '.', './', '././', or reduced to nothing). It then validates each component via validatePathComponent, so this specific message means the path as a whole carried no content.","triggerScenarios":"Calling SanitizeResourcePath with \".\", \"./\", \"\", or a string of only slashes/dots that path.Clean collapses to the root; also hit when a caller strips a prefix and nothing remains.","commonSituations":"Off-by-one string trimming that consumes the filename; a client sending a directory path instead of a file; an empty form field that passed a weaker upstream check.","solutions":["Check that the input names an actual file before calling the API (non-empty basename after trimming)","Reject \".\" and empty strings at your entry point with a clearer message","Use SanitizeResourceFileName when you expect a bare filename, which produces a clearer 'file name is required' error","Trace where the value came from — usually a TrimPrefix or path.Dir call that removed too much"],"exampleFix":"// before\nname, err := resources.SanitizeResourcePath(\"./\")\n// after\nbase := path.Base(strings.TrimSpace(input))\nif base == \".\" || base == \"/\" {\n    return fmt.Errorf(\"a file name is required, got %q\", input)\n}\nname, err := resources.SanitizeResourcePath(input)","handlingStrategy":"validation","validationCode":"func isMeaningfulPath(p string) bool {\n\ttrimmed := strings.TrimSpace(p)\n\tcleaned := path.Clean(\"/\" + strings.ReplaceAll(trimmed, \"\\\\\", \"/\"))\n\trel := strings.TrimPrefix(cleaned, \"/\")\n\treturn rel != \"\" && rel != \".\"\n}","typeGuard":null,"tryCatchPattern":"name, err := resources.SanitizeResourcePath(input)\nif err != nil {\n\tif strings.Contains(err.Error(), \"invalid path\") {\n\t\treturn fmt.Errorf(\"path %q does not name a file\", input)\n\t}\n\treturn err\n}","preventionTips":["Require a non-empty basename before invoking path sanitization","Reject \".\" and directory-only inputs at the form/API layer with a clear message","Beware TrimPrefix/path.Dir operations that can reduce a path to nothing","Prefer SanitizeResourceFileName when the input is expected to be a bare filename"],"tags":["path-validation","empty-path","input-validation"],"backgroundTag":"invalid-path","analyzedSha":"ea665308baaff015b226f308438a68d929d0f29b","analyzedAt":"2026-09-01T14:16:31.421Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}