can1357/oh-my-pi · error
${name} exceeds the ${SHARPSHOOTER_MAX_FILE_LINES}-line limi
Error message
${name} exceeds the ${SHARPSHOOTER_MAX_FILE_LINES}-line limit What it means
Each replacement file's content, after secret redaction, is line-counted (newlines counted by scanning char codes). If a file exceeds SHARPSHOOTER_MAX_FILE_LINES lines, this error aborts consolidation so memory files stay small and useful.
Source
Thrown at packages/coding-agent/src/sharpshooter/consolidate.ts:262
const files: ReplacementFile[] = [];
for (const item of args.files) {
if (!item || typeof item !== "object" || !("name" in item) || !("content" in item)) {
throw new Error("replace_memory_files contains an invalid file entry");
}
const name = item.name;
const rawContent = item.content;
if (!isMemoryFileName(name) || typeof rawContent !== "string") {
throw new Error("replace_memory_files contains an invalid file entry");
}
if (seen.has(name)) throw new Error(`replace_memory_files contains duplicate ${name}`);
seen.add(name);
const redacted = redactSecrets(rawContent);
let lines = redacted.length > 0 ? 1 : 0;
for (let index = 0; index + 1 < redacted.length; index++) {
if (redacted.charCodeAt(index) === 10) lines += 1;
}
if (lines > SHARPSHOOTER_MAX_FILE_LINES) {
throw new Error(`${name} exceeds the ${SHARPSHOOTER_MAX_FILE_LINES}-line limit`);
}
files.push({ name, content: redacted });
}
const totalChars = files.reduce((sum, file) => sum + file.content.trim().length, 0);
if (totalChars === 0 && SHARPSHOOTER_MEMORY_FILES.some(name => currentFiles[name].trim().length > 0)) {
throw new Error("replace_memory_files returned all-empty content; refusing to wipe memory files");
}
return files;
}
function isMemoryFileName(value: unknown): value is SharpshooterMemoryFile {
return typeof value === "string" && (SHARPSHOOTER_MEMORY_FILES as readonly string[]).includes(value);
}
async function applyReplacementFiles(bankDir: string, files: readonly ReplacementFile[]): Promise<void> {
const staged = files.map(file => ({
...file,
tempPath: path.join(bankDir, `.${file.name}.${process.pid}.${crypto.randomUUID()}.tmp`),View on GitHub (pinned to 9690622007)
Solutions
- Condense the file content to a terse summary under the line limit.
- Split content across the other allowed memory files where appropriate.
- Move detail out to project files and keep only pointers in memory.
- Retry with a stronger model or prompt emphasizing the per-file line budget.
Example fix
// before: 400-line dump content: <full session log> // after: compact summary content: "- auth: uses JWT in src/auth.ts\n- db: sqlite via bun:sqlite"
Defensive patterns
Strategy: validation
Validate before calling
const lineCount = (s: string) => (s.length ? 1 + [...s].filter(c => c === "\n").length : 0);
files.forEach(f => { if (lineCount(f.content) > MAX_LINES) throw new Error(`${f.name} too long`); }); Type guard
null
Try / catch
try {
files = parseReplacementFiles(call, currentFiles);
} catch (err) {
if (String(err).includes("-line limit")) {
// retry with instruction to condense
}
} Prevention
- State the exact line budget in the tool description and prompt.
- Summarize rather than transcribe session content into memory files.
- Periodically prune memory files during consolidation.
When it happens
Trigger: A model writes an overly verbose memory file whose redacted content contains more than SHARPSHOOTER_MAX_FILE_LINES newlines.
Common situations: Models pasting whole conversation logs into memory files; accumulating changelogs instead of summaries; low-effort models ignoring the length instruction in the tool description.
Related errors
- Managed skill is ${bytes} bytes; the limit is ${MAX_MANAGED_
- Summary exceeds ${config.summaryHardLimit} bytes
- xAI image edits accept up to ${XAI_MAX_EDIT_IMAGES} referenc
- ${error.message}
- Image file too large: ${formatBytes(inputBytes)} exceeds ${f
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/56bb05e0f65ec175.
Report an issue: GitHub.