{"record":{"id":"3cd56e25d79843e8","repo":"vxcontrol/pentagi","slug":"file-name-is-required-3cd56e","errorCode":null,"errorMessage":"file name is required","messagePattern":"file name is required","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"backend/pkg/resources/resources.go","lineNumber":185,"sourceCode":"\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\n\t}\n\treturn SanitizeResourcePath(p)\n}\n\n// SanitizeResourceFileName strips path separators and validates the basename.\nfunc SanitizeResourceFileName(fileName string) (string, error) {\n\ttrimmed := strings.TrimSpace(fileName)\n\tif trimmed == \"\" {\n\t\treturn \"\", fmt.Errorf(\"file name is required\")\n\t}\n\n\tnormalized := strings.ReplaceAll(trimmed, \"\\\\\", \"/\")\n\tcleanName := path.Base(path.Clean(\"/\" + normalized))\n\n\tif err := validatePathComponent(cleanName); err != nil {\n\t\treturn \"\", err\n\t}\n\treturn cleanName, nil\n}\n\n// FilePath builds the virtual file path for a file named name inside dir.\n// dir may be \"\" (root).\nfunc FilePath(dir, name string) string {\n\tif dir == \"\" {\n\t\treturn name\n\t}\n\treturn dir + \"/\" + name","sourceCodeStart":167,"sourceCodeEnd":203,"githubUrl":"https://github.com/vxcontrol/pentagi/blob/ea665308baaff015b226f308438a68d929d0f29b/backend/pkg/resources/resources.go#L167-L203","documentation":"SanitizeResourceFileName requires a non-empty basename; it strips whitespace and returns this error when nothing remains. The function's job is to reduce an input to a safe bare filename (dropping any directory components) and validate it.","triggerScenarios":"Calling SanitizeResourceFileName with \"\", \"   \", or a string that becomes empty after trimming, from callers like UploadResources or anonymous handler closures processing multipart file fields.","commonSituations":"A multipart upload with no filename part (e.g. curl --data-binary without -F filename, or a programmatically built form); a frontend sending an empty name field; a missing Content-Disposition filename header.","solutions":["Ensure the client always sends a filename in the multipart part (Content-Disposition filename field)","Check for emptiness in your handler before calling the API and return a user-facing message","Provide a generated fallback name (e.g. timestamp or hash-based) when the original is absent","Verify the frontend form marks the file input as required"],"exampleFix":"// before\nname, err := resources.SanitizeResourceFileName(fileHeader.Filename)\n// after\nfname := strings.TrimSpace(fileHeader.Filename)\nif fname == \"\" {\n    fname = fmt.Sprintf(\"upload-%d.bin\", time.Now().UnixNano())\n}\nname, err := resources.SanitizeResourceFileName(fname)","handlingStrategy":"validation","validationCode":"func hasFileName(fh *multipart.FileHeader) bool {\n\treturn fh != nil && strings.TrimSpace(fh.Filename) != \"\"\n}","typeGuard":null,"tryCatchPattern":"name, err := resources.SanitizeResourceFileName(fh.Filename)\nif err != nil {\n\tif strings.Contains(err.Error(), \"file name is required\") {\n\t\treturn http.StatusBadRequest\n\t}\n\treturn err\n}","preventionTips":["Mark file inputs as required in forms and enforce filename presence server-side","Generate a fallback name when clients omit the multipart filename","Check Content-Disposition parsing — some HTTP clients omit filename for blob bodies","Return 400 with a user-facing message instead of leaking the raw wrapped error"],"tags":["validation","file-upload","empty-value"],"backgroundTag":"missing-filename","analyzedSha":"ea665308baaff015b226f308438a68d929d0f29b","analyzedAt":"2026-09-01T14:16:31.421Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}