FlowiseAI/Flowise · error · Error
Invalid file path: key is required and must be a string
Error message
Invalid file path: key is required and must be a string
What it means
Thrown by getSafeFilePath(baseDir, key) when `key` is falsy or not a string. getSafeFilePath is the hard boundary that resolves an untrusted relative key/filename to an absolute path guaranteed to stay inside baseDir, so it refuses any key it cannot treat as text. The check happens before percent-decoding, null-byte scanning, and the path.relative containment test, so a missing key fails fast and early.
Source
Thrown at packages/components/src/validator.ts:446
baseName = baseName.replace(/^\.+/, '')
if (!baseName || isUnsafeFilePath(baseName)) {
throw new Error(`Invalid or unsafe file name: ${name}`)
}
return baseName
}
/**
* Safely resolve an untrusted relative key/filename to an absolute path inside a
* trusted base directory, guaranteeing the result cannot escape that directory.
*
* @param {string} baseDir The trusted base directory (e.g. a freshly created temp dir)
* @param {string} key The untrusted relative key or filename
* @returns {string} A validated absolute path guaranteed to be within baseDir
* @throws {Error} If key is missing/invalid or the resolved path escapes baseDir
*/
export const getSafeFilePath = (baseDir: string, key: string): string => {
if (!key || typeof key !== 'string') {
throw new Error('Invalid file path: key is required and must be a string')
}
let decodedKey = key
try {
decodedKey = decodeURIComponent(key)
} catch {
// malformed percent-encoding — keep the raw key; resolve/relative handle it safely
}
if (decodedKey.includes('\0')) {
throw new Error(`Invalid file path: null byte detected in "${key}"`)
}
const resolvedBase = path.resolve(baseDir)
const resolvedPath = path.resolve(resolvedBase, decodedKey)
if (process.env.PATH_TRAVERSAL_SAFETY === 'false') {
return resolvedPathView on GitHub (pinned to abe4a8601a)
Solutions
- Validate the key at the controller boundary and return 400 before calling getSafeFilePath.
- Guard with a type check: `if (typeof key !== 'string' || key.length === 0)` then reject the request.
- If empty keys are semantically invalid for your flow, assert that upstream (e.g. the upload step that stores the key).
Example fix
// before
const abs = getSafeFilePath(baseDir, req.query.key) // req.query.key may be undefined
// after
const key = req.query.key
if (typeof key !== 'string' || key.length === 0) {
return res.status(400).json({ message: 'key is required' })
}
const abs = getSafeFilePath(baseDir, key) Defensive patterns
Strategy: validation
Validate before calling
if (typeof key !== 'string' || key.length === 0) {
return res.status(400).json({ message: 'A non-empty key is required' })
}
const abs = getSafeFilePath(baseDir, key) Type guard
const isNonEmptyKey = (v: unknown): v is string =>
typeof v === 'string' && v.length > 0 Try / catch
try {
const abs = getSafeFilePath(baseDir, key)
} catch (e) {
return res.status(400).json({ message: (e as Error).message })
} Prevention
- Validate key presence in the controller before resolving paths.
- Ensure DB columns that hold storage keys are NOT NULL.
- Type route params as string and reject missing ones via schema validation.
When it happens
Trigger: Calling getSafeFilePath(tmpDir, undefined), getSafeFilePath(tmpDir, null), getSafeFilePath(tmpDir, ''), or getSafeFilePath(tmpDir, 0). Typically reached from a storage/attachment handler that resolves an object key from a request param, query, or DB column that was null/empty.
Common situations: A route handler that reads req.params.key but the client omitted it; a DB row whose storageKey column is NULL; a refactor that renamed the field and left the old accessor returning undefined; integration tests that pass an empty key.
Related errors
- Invalid file name: name is required
- Failed to parse Supabase filter: ${error.message}
- Invalid or unsafe fileName detected
- Invalid filename after sanitization
- Invalid path characters detected
AI-assisted analysis of FlowiseAI/Flowise@abe4a8601a (2026-08-12).
Data as JSON: /api/errors/88ce9856a28e9001.
Report an issue: GitHub.