expressjs/express · error · TypeError
path must be a string to res.sendFile
Error message
path must be a string to res.sendFile
What it means
Thrown by `res.sendFile` when a truthy `path` argument is not a string (e.g. a Buffer, number, array, or object). The path is later passed to `encodeURI` and the `send` module, both of which require a string, so Express rejects other types up front.
Source
Thrown at lib/response.js:385
* });
* });
*
* @public
*/
res.sendFile = function sendFile(path, options, callback) {
var done = callback;
var req = this.req;
var res = this;
var next = req.next;
var opts = options || {};
if (!path) {
throw new TypeError('path argument is required to res.sendFile');
}
if (typeof path !== 'string') {
throw new TypeError('path must be a string to res.sendFile')
}
// support function as second arg
if (typeof options === 'function') {
done = options;
opts = {};
}
if (!opts.root && !pathIsAbsolute(path)) {
throw new TypeError('path must be absolute or specify root to res.sendFile');
}
// create file stream
var pathname = encodeURI(path);
// wire application etag option to send
opts.etag = this.app.enabled('etag');
var file = send(req, pathname, opts);View on GitHub ↗ (pinned to a3714473fe)
Solutions
- Pass the filesystem path string, not the file's contents or an object: `res.sendFile('/abs/path/file.txt')`.
- If using a URL or Path-like object, convert it first (e.g. `fileURLToPath(url)` or `String(p)`).
- If the value comes from req.query, reject non-string values (repeat params arrive as arrays).
Example fix
// before res.sendFile(fs.readFileSync(filePath)); // after res.sendFile(filePath); // sendFile reads the file itself
Defensive patterns
Strategy: type-guard
Validate before calling
if (typeof filePath !== 'string') {
return next(new TypeError('resolved file path is not a string'));
}
res.sendFile(filePath, { root: PUBLIC_DIR }); Type guard
function isPathString(p) {
return typeof p === 'string' && p.length > 0;
} Prevention
- req.query values can be arrays (?file=a&file=b) or objects — never assume a string; check typeof first
- Reject non-string path inputs at the route boundary with a 400 rather than passing them through
- Use a validation library (zod/joi) on request inputs that feed file paths
When it happens
Trigger: `res.sendFile(fs.readFileSync(p))` (passing file contents instead of the path), `res.sendFile(['a.txt'])`, `res.sendFile({ path: p })`, or passing a URL/Path object instead of a string.
Common situations: Confusing sendFile (takes a path) with res.send (takes a body); passing a `URL` or `path`-like object from a library; array-valued query params (`?file=a&file=b`) producing an array from req.query.
Related errors
- path argument is required to res.sendFile
- path must be absolute or specify root to res.sendFile
- Content-Type cannot be set to an Array
- Url must be a string
- ECONNABORTED
AI-assisted analysis of expressjs/express@a3714473fe (2026-07-31).
Data as JSON: /data/errors/63fd865fb5001160.json.
Report an issue: GitHub ↗.