{"record":{"id":"ee3a69b1d5d5d3e3","repo":"vxcontrol/pentagi","slug":"path-query-parameter-is-required","errorCode":null,"errorMessage":"path query parameter is required","messagePattern":"path query parameter is required","errorType":"validation","errorClass":null,"httpStatus":400,"severity":"error","filePath":"backend/pkg/flowfiles/files.go","lineNumber":99,"sourceCode":"func FlowDataDir(dataDir string, flowID uint64) string {\n\treturn filepath.Join(dataDir, fmt.Sprintf(\"flow-%d-data\", flowID))\n}\n\nfunc FlowUploadsDir(dataDir string, flowID uint64) string {\n\treturn filepath.Join(FlowDataDir(dataDir, flowID), UploadsDirName)\n}\n\nfunc FlowContainerDir(dataDir string, flowID uint64) string {\n\treturn filepath.Join(FlowDataDir(dataDir, flowID), ContainerDirName)\n}\n\nfunc FlowResourcesDir(dataDir string, flowID uint64) string {\n\treturn filepath.Join(FlowDataDir(dataDir, flowID), ResourcesDirName)\n}\n\nfunc ResolveCachedPath(dataDir string, flowID uint64, reqPath string) (string, error) {\n\tif strings.TrimSpace(reqPath) == \"\" {\n\t\treturn \"\", errors.New(\"path query parameter is required\")\n\t}\n\n\tcleaned := filepath.Clean(filepath.FromSlash(strings.ReplaceAll(reqPath, \"\\\\\", \"/\")))\n\tif filepath.IsAbs(cleaned) {\n\t\treturn \"\", fmt.Errorf(\"path must be relative (no leading /)\")\n\t}\n\n\tparts := strings.SplitN(cleaned, string(filepath.Separator), 2)\n\tif parts[0] != UploadsDirName && parts[0] != ContainerDirName && parts[0] != ResourcesDirName {\n\t\treturn \"\", fmt.Errorf(\"path must start with '%s', '%s', or '%s'\", UploadsDirName, ContainerDirName, ResourcesDirName)\n\t}\n\n\tflowDataDir := FlowDataDir(dataDir, flowID)\n\tabsPath := filepath.Join(flowDataDir, cleaned)\n\tif !IsWithinDir(absPath, flowDataDir) {\n\t\treturn \"\", fmt.Errorf(\"path escapes the flow data directory\")\n\t}\n","sourceCodeStart":81,"sourceCodeEnd":117,"githubUrl":"https://github.com/vxcontrol/pentagi/blob/ea665308baaff015b226f308438a68d929d0f29b/backend/pkg/flowfiles/files.go#L81-L117","documentation":"ResolveCachedPath validates a user-supplied path for accessing flow files before any filesystem access. It rejects an empty or whitespace-only reqPath because a blank path cannot be resolved to any file inside the flow's data directory. The check is the first guard in a chain that also enforces relative paths and an allow-listed directory prefix.","triggerScenarios":"Calling ResolveCachedPath (directly or via AddResourceFromFlow / the HTTP handler calling it) with an empty string, a string of spaces/tabs, or omitting the required path query parameter on the request that triggers this resolver.","commonSituations":"A frontend or script hits the flow-files endpoint without appending ?path=...; a tool integration builds the URL with an empty variable because the file path was never populated; URL encoding drops the parameter entirely.","solutions":["Pass a non-empty path, e.g. 'uploads/report.pdf', 'containers/...', or 'resources/...' as the path query parameter","Check the caller: if the path comes from user input, validate non-empty before invoking the API","If building URLs programmatically, ensure the query parameter is actually included and not stripped by a template or client"],"exampleFix":"// before\nclient.get(`/flows/${flowID}/files?path=`)\n// after\nclient.get(`/flows/${flowID}/files?path=${encodeURIComponent('uploads/report.pdf')}`)","handlingStrategy":"validation","validationCode":"if (!reqPath || !reqPath.trim()) throw new Error('path query parameter is required before calling the API');","typeGuard":"const hasPath = (p: unknown): p is string => typeof p === 'string' && p.trim().length > 0;","tryCatchPattern":"try {\n  const resolved = await api.resolveCachedPath(flowID, reqPath);\n} catch (e) {\n  if (e.message.includes('path query parameter is required')) {\n    // prompt user / fix caller to supply a path\n  }\n}","preventionTips":["Always validate the path field is non-empty before building the request URL","Use encodeURIComponent when inserting paths into query strings","Set a default/fallback path in UI forms so the parameter is never blank"],"tags":["input-validation","path-resolution"],"backgroundTag":"missing-required-argument","analyzedSha":"ea665308baaff015b226f308438a68d929d0f29b","analyzedAt":"2026-09-01T14:16:31.421Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}