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

  1. List the parent directory instead: ops.ls('src') rather than ops.ls('src/index.ts').
  2. Use ops.readFile(path) when the goal is the file's content, not a listing.
  3. Check the path type first via ops.bash(`test -d ${path} && echo dir || echo file`).
  4. 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

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


AI-assisted analysis of vercel/ai@69428b1f8b (2026-08-30). Data as JSON: /api/errors/e36a88d5b46d49d6. Report an issue: GitHub.