vercel/ai · error · Error
Not a directory: ${inputPath}
Error message
Not a directory: ${inputPath} What it means
Thrown by ls when the path exists but is not a directory: the shell probe echoes __CLINE_LS_NOT_DIR__ (`[ ! -d target ]`, exit 3) and the library throws 'Not a directory'. ls only lists directories, so file paths must be listed via their parent directory instead.
Source
Thrown at packages/harness-cline/src/cline-remote-ops.ts:384
const result = await runShell({
command: [
`if [ ! -e ${shellQuote(
target,
)} ]; then echo "__CLINE_LS_NOT_FOUND__"; exit 2; fi`,
`if [ ! -d ${shellQuote(
target,
)} ]; then echo "__CLINE_LS_NOT_DIR__"; exit 3; fi`,
`cd ${shellQuote(target)}`,
'ls -1Ap',
].join('; '),
});
const output = result.output.trim();
if (output.includes('__CLINE_LS_NOT_FOUND__')) {
throw new Error(`Path not found: ${inputPath}`);
}
if (output.includes('__CLINE_LS_NOT_DIR__')) {
throw new Error(`Not a directory: ${inputPath}`);
}
return output
.split('\n')
.filter(Boolean)
.map(line => line.replace(/[*=@|]$/, ''))
.sort((left, right) =>
left.toLowerCase().localeCompare(right.toLowerCase()),
)
.slice(0, limit);
},
};
}
View on GitHub (pinned to 69428b1f8b)
Solutions
- List the parent directory instead: ops.ls('src') rather than ops.ls('src/index.ts').
- Use ops.readFile(path) when the goal is the file's content, not a listing.
- Check the path type first via ops.bash(`test -d ${path} && echo dir || echo file`).
- Resolve symlinks (ops.bash 'readlink -f <path>') to see what the path actually points to.
Example fix
// before: ls a file
await ops.ls('src/index.ts'); // Not a directory: src/index.ts
// after: read the file, list the dir
const content = await ops.readFile('src/index.ts');
const entries = await ops.ls('src'); Defensive patterns
Strategy: validation
Validate before calling
async function assertIsDirectory(ops, dir) {
const r = await ops.bash(`test -d ${JSON.stringify(dir)} && echo dir || echo notdir`);
if (!r.output.includes('dir')) throw new Error(`not a directory: ${dir}`);
} Try / catch
try {
return await ops.ls(dir);
} catch (e) {
if (e instanceof Error && e.message.startsWith('Not a directory:')) {
return ops.ls(path.posix.dirname(dir)); // list the parent instead
}
throw e;
} Prevention
- Only pass directory paths to ls; use readFile for file contents.
- Check path type with `test -d` when the model-supplied path is ambiguous.
- Resolve symlinks with readlink -f to see the real target type.
- List the parent directory when you only know a file path.
When it happens
Trigger: ops.ls('src/index.ts') — passing a file path to ls; ls on a symlink pointing to a file; agents confusing file and directory paths while exploring the workspace.
Common situations: Agent tool loops that ls a known file to 'inspect' it; following a symlinked path that resolves to a file; scripted calls that pass whatever path the model produced without checking its type.
Related errors
- File not found: ${inputPath}
- Text to replace was not found in ${inputPath}
- Path not found: ${input.path ?? '.'}
- `Failed to create sandbox work directory ${workDir} (exit ${
- Cannot write harness skill '${skillName}': ${skillDir} alrea
AI-assisted analysis of vercel/ai@69428b1f8b (2026-08-30).
Data as JSON: /api/errors/e36a88d5b46d49d6.
Report an issue: GitHub.