remix-run/remix · error · TypeError
Expected a Remix config file or directory: ${fromPath}
Error message
Expected a Remix config file or directory: ${fromPath} What it means
loadConfig accepts a path to a remix config file or its containing directory. If the path exists but is neither a regular file nor a directory (or stat reports something else), this TypeError is thrown.
Source
Thrown at packages/cli/src/lib/remix-config.ts:146
* @returns The validated Remix project configuration, or an empty object when no config is found.
*/
export async function loadConfig(from: string | URL = process.cwd()): Promise<RemixConfig> {
let fromPath = path.resolve(from instanceof URL ? fileURLToPath(from) : from)
let stat
try {
stat = await fs.stat(fromPath)
} catch (error) {
if (isNodeError(error) && error.code === 'ENOENT') throw remixConfigNotFound(fromPath)
throw error
}
if (stat.isFile()) {
return loadRemixConfig(path.dirname(fromPath), path.basename(fromPath))
}
if (!stat.isDirectory()) {
throw new TypeError(`Expected a Remix config file or directory: ${fromPath}`)
}
let configDir = await findAppRoot(fromPath, 'remix.json')
return configDir === null ? {} : loadRemixConfig(configDir, undefined)
}
export async function loadRemixConfig(
cwd: string,
configPath: string | undefined,
): Promise<RemixConfig> {
let filePath = path.resolve(cwd, configPath ?? 'remix.json')
let text: string
try {
text = await fs.readFile(filePath, 'utf8')
} catch (error) {
if (isNodeError(error) && error.code === 'ENOENT') {
if (configPath === undefined) return {}View on GitHub (pinned to 9696913134)
Solutions
- Verify the path points to remix.json or its directory: `ls -l <path>`
- Remove pipes/devices and pass a real file path
- If generating the path in a script, assert fs.statSync(path).isFile() before calling loadConfig
Example fix
# before
loadConfig('/tmp/routes-pipe')
# after
loadConfig('/path/to/app/remix.json') Defensive patterns
Strategy: try-catch
Validate before calling
let stat = fs.statSync(configPath)
if (!stat.isFile() && !stat.isDirectory()) throw new TypeError('bad config path') Try / catch
try { await loadConfig(p) } catch (e) { if (e instanceof TypeError && e.message.includes('Expected a Remix config')) { /* fix path */ } throw e } Prevention
- Assert the config path is a file before loading
- Avoid pipes/devices/special files in config paths
- Validate dynamically built paths in scripts
When it happens
Trigger: Calling loadConfig with a path that is a FIFO, socket, device, or a broken entry; less commonly, a race where the path is replaced between stat and classification.
Common situations: Pointing tooling at /dev/null or a named pipe instead of remix.json; passing a symlink to a removed file; scripts that generate the config path dynamically.
Related errors
- throw new AssertionError({ message, actual, expected, operat
- expect(received).toThrow() requires a function (got ${typeof
- expected promise to resolve, but it rejected with: ${stringi
- expected promise to reject, but it resolved with: ${stringif
- throw new TypeError(message)
AI-assisted analysis of remix-run/remix@9696913134 (2026-08-27).
Data as JSON: /api/errors/bb403e782c6e0750.
Report an issue: GitHub.