can1357/oh-my-pi · error
Terminal-Bench tasks directory contains no task.toml files:
Error message
Terminal-Bench tasks directory contains no task.toml files: ${absolute} What it means
validateTasksDir also throws when the directory exists and is readable but none of its immediate subdirectories contain a task.toml file — meaning it is not a Terminal-Bench tasks root (you may have pointed at the repo root instead of its tasks/ folder, or at the wrong checkout level).
Source
Thrown at packages/metaharness/src/tb/dataset.ts:32
} catch (error) {
if (isEnoent(error)) return "missing";
throw error;
}
}
async function validateTasksDir(tasksDir: string): Promise<string> {
const absolute = path.resolve(tasksDir);
try {
const entries = await fs.readdir(absolute, { withFileTypes: true });
for (const entry of entries) {
if (!entry.isDirectory()) continue;
if (await Bun.file(path.join(absolute, entry.name, "task.toml")).exists()) return absolute;
}
} catch (error) {
if (isEnoent(error)) throw new Error(`Terminal-Bench tasks directory does not exist: ${absolute}`);
throw error;
}
throw new Error(`Terminal-Bench tasks directory contains no task.toml files: ${absolute}`);
}
function repositoryName(source: string): string {
const trimmed = source.replace(/\/+$/, "");
const basename = trimmed.slice(trimmed.lastIndexOf("/") + 1).replace(/\.git$/, "");
if (!basename) throw new Error(`Cannot determine repository name from dataset source: ${source}`);
return basename;
}
function gitError(action: string, source: string, stderr: Uint8Array): Error {
const detail = new TextDecoder().decode(stderr).trim();
return new Error(`${action} ${source} failed${detail ? `: ${detail}` : ""}`);
}
export async function resolveDataset(source: string, cacheDir: string): Promise<string> {
const sourceKind = await directoryStat(source);
if (sourceKind === "directory") {
const absoluteSource = path.resolve(source);View on GitHub (pinned to 9690622007)
Solutions
- Point --dataset at the directory whose subdirectories each contain task.toml (often <repo>/tasks)
- Verify the cloned repo is intact (git status; non-empty tasks/) and re-clone if needed
- If layout changed upstream, pass the nested tasks path explicitly (resolveDataset already tries <dir>/tasks)
Example fix
// before --dataset ~/terminal-bench # repo root, no */task.toml // after --dataset ~/terminal-bench/tasks # contains hello-world/task.toml ...
Defensive patterns
Strategy: validation
Validate before calling
import * as fs from "node:fs/promises";
import * as path from "node:path";
const entries = await fs.readdir(dir, { withFileTypes: true });
const hasTask = entries.some(async e => e.isDirectory() && await Bun.file(path.join(dir, e.name, "task.toml")).exists());
if (!hasTask) throw new Error(`${dir} has no */task.toml`); Prevention
- Point --dataset at the tasks/ root containing per-task task.toml files
- Spot-check the checkout layout after upstream updates
- Re-clone if the repo appears empty or restructured
When it happens
Trigger: resolveDataset passes a directory whose child directories all lack task.toml, e.g. pointing at a Terminal-Bench repo root instead of tasks/, or a checkout of a different project.
Common situations: Dataset dir has an unexpected layout after upstream restructure; user passed a parent directory; empty cloned repo (shallow/failed checkout with no task subdirs).
Related errors
- Terminal-Bench tasks directory does not exist: ${absolute}
- Terminal-Bench dataset source is not a directory: ${source}
- Terminal-Bench dataset source does not exist: ${source}
- unknown filetype: {ft_debug}
- Is a directory
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/73e89402afe9de89.
Report an issue: GitHub.