tinyhumansai/openhuman · error · SpecError
globs not allowed — use directory prefixes (got "${p}")
Error message
globs not allowed — use directory prefixes (got "${p}") What it means
owned_paths entries must not contain the glob characters * or ? — the error text says "use directory prefixes". The reason is architectural: findOverlaps() enforces disjoint ownership via plain string prefix containment (comparePaths normalizes trailing slashes and checks startsWith), which cannot reason about glob semantics. A glob would silently defeat the overlap detector, so it is banned up front; the offending path is shown with index-precise path.
Source
Thrown at scripts/agent-batch/lib.mjs:154
throw new SpecError(`duplicate branch "${agent.branch}"`, `${at}.branch`);
}
seenBranch.add(agent.branch);
if (!Array.isArray(agent.owned_paths) || agent.owned_paths.length === 0) {
throw new SpecError(
"owned_paths must be a non-empty array",
`${at}.owned_paths`,
);
}
for (let j = 0; j < agent.owned_paths.length; j++) {
const p = agent.owned_paths[j];
if (typeof p !== "string" || p.length === 0) {
throw new SpecError(
"must be a non-empty string",
`${at}.owned_paths[${j}]`,
);
}
if (p.includes("*") || p.includes("?")) {
throw new SpecError(
`globs not allowed — use directory prefixes (got "${p}")`,
`${at}.owned_paths[${j}]`,
);
}
if (p.startsWith("/")) {
throw new SpecError(
`paths must be repo-relative, not absolute (got "${p}")`,
`${at}.owned_paths[${j}]`,
);
}
}
if ("allowed_shared_paths" in agent) {
if (!Array.isArray(agent.allowed_shared_paths)) {
throw new SpecError("must be an array", `${at}.allowed_shared_paths`);
}
}
if ("labels" in agent && !Array.isArray(agent.labels)) {
throw new SpecError("must be an array", `${at}.labels`);View on GitHub (pinned to a221052e0d)
Solutions
- Replace globs with the enclosing directory prefix: "src/**/*.rs" → "src/" or a narrower "src/openhuman/web3/"
- Own whole directories even if the agent touches only some files — overlap rules compare prefixes, so pick the deepest directory that covers the work
- For a single file, use the file path itself ("app/src/App.tsx") — file paths have no glob chars
Example fix
// before "owned_paths": ["src/openhuman/**/*.rs"] // after "owned_paths": ["src/openhuman/web3/"]
Defensive patterns
Strategy: validation
Validate before calling
for (const [i, a] of spec.agents.entries()) {
for (const [j, p] of a.owned_paths.entries()) {
if (typeof p === "string" && (p.includes("*") || p.includes("?"))) {
console.error(`agents[${i}].owned_paths[${j}] uses a glob — replace with a directory prefix`);
process.exit(1);
}
}
} Try / catch
try {
validateSpec(spec);
} catch (e) {
if (e instanceof SpecError && /globs not allowed/.test(e.message)) {
console.error(`rewrite as a directory prefix (e.g. "src/openhuman/web3/"): ${e.message}`);
process.exit(1);
}
throw e;
} Prevention
- Remember owned_paths is prefix-based, not glob-based — think directories, not patterns
- Do not copy scopes from .gitignore/CODEOWNERS/CI path filters into specs
- After fixing paths, also run findOverlaps(spec) from lib.mjs to confirm agents stay disjoint
When it happens
Trigger: "owned_paths": ["src/**/*.rs"], ["app/src/*"], or ["docs?.md"] on any agent. Any occurrence of * or ? anywhere in the path string triggers it.
Common situations: Porting file-scopes from .gitignore or CODEOWNERS syntax, which is glob-based; trying to express "all Rust files" instead of owning the directories; copy-pasting glob patterns from CI path filters.
Related errors
- owned_paths must be a non-empty array
- must be a non-empty string
- batch_id must be a kebab-case slug
- base_repo must be "tinyhumansai/openhuman" (got "${spec.base
- base_branch must be "main" (got "${spec.base_branch}")
AI-assisted analysis of tinyhumansai/openhuman@a221052e0d (2026-08-16).
Data as JSON: /api/errors/bccf8b99862d327d.
Report an issue: GitHub.