Summary
buildUserAnalysisContext embeds the raw content of the recent prompts into the profile-learning prompt with no per-item size cap, and the profile-analysis prompt is not excluded from later passes. A prior analysis prompt gets saved as a user prompt, then re-embedded into the next analysis, nesting recursively until the request exceeds the model window. Profile learning (and often auto-capture) then fails:
prompt is too long: N tokens > 1000000 maximum
ContextOverflowError: Session too large to compact
The user_prompts table fills with these ever-larger self-referential rows and the DB bloats without bound.
Likely also the root cause behind #170's overflow comment ("keeps sending everything over and over... context so large it overflows... input is too large").
Root cause
-
Uncapped prompt embedding in buildUserAnalysisContext (user-memory-learning.js):
prompts.map((p, i) => `${i + 1}. ${p.content}`).join("\n\n")
Each content is inserted verbatim; a large recent prompt (pasted log, image data URL, or a prior analysis prompt) can exceed the window on its own.
-
The persist-time guard misses the analysis prompt. isStructuredSummaryPromptMessage:
return userMessage.includes("Analyze this conversation.") && userMessage.includes('type="skip"');
The profile-learning prompt starts with # User Profile Analysis and matches neither string, so it is persisted via savePrompt and re-ingested next cycle. Growth compounds each pass.
Related: changelog snapshots store embeddings
Each user_profile_changelogs.profile_data_snapshot stores a full profile copy, dominated by the centroid/anchor embedding vectors on every item. Those vectors are needed on the live profile for similarity matching but are dead weight in changelog history, so user-profiles.db bloats far beyond the actual profile content.
Impact
- Profile learning / auto-capture fail on every idle once the loop takes hold.
user-prompts.db grows without bound.
- Surfaces as a recurring toast unrelated to current session size, so it looks like an OpenCode core problem.
Suggested fix
-
In buildUserAnalysisContext, skip analysis prompts and cap each embedded prompt:
prompts.map((p, i) => {
const c = p.content || "";
if (c.includes("# User Profile Analysis")) return `${i + 1}. [skipped: internal analysis prompt]`;
const capped = c.length > 4000 ? c.slice(0, 4000) + "..." : c;
return `${i + 1}. ${capped}`;
}).join("\n\n")
-
Broaden the persist-time guard so the analysis prompt is never saved (match # User Profile Analysis, or check before savePrompt).
-
Cap total assembled prompt size and strip image data URLs from stored content.
-
Strip centroid/anchor (embedding fields) from profile_data_snapshot before persisting a changelog entry.
Workaround
DELETE FROM user_prompts WHERE content LIKE '%# User Profile Analysis%';
VACUUM;
(Back up user-prompts.db first.)
Environment
- opencode-mem v2.19.4, OpenCode v1.18.3 (Bun), macOS
- Provider: amazon-bedrock, model global.anthropic.claude-sonnet-5 (1M window)
Summary
buildUserAnalysisContextembeds the rawcontentof the recent prompts into the profile-learning prompt with no per-item size cap, and the profile-analysis prompt is not excluded from later passes. A prior analysis prompt gets saved as a user prompt, then re-embedded into the next analysis, nesting recursively until the request exceeds the model window. Profile learning (and often auto-capture) then fails:The
user_promptstable fills with these ever-larger self-referential rows and the DB bloats without bound.Likely also the root cause behind #170's overflow comment ("keeps sending everything over and over... context so large it overflows... input is too large").
Root cause
Uncapped prompt embedding in
buildUserAnalysisContext(user-memory-learning.js):Each
contentis inserted verbatim; a large recent prompt (pasted log, image data URL, or a prior analysis prompt) can exceed the window on its own.The persist-time guard misses the analysis prompt.
isStructuredSummaryPromptMessage:The profile-learning prompt starts with
# User Profile Analysisand matches neither string, so it is persisted viasavePromptand re-ingested next cycle. Growth compounds each pass.Related: changelog snapshots store embeddings
Each
user_profile_changelogs.profile_data_snapshotstores a full profile copy, dominated by thecentroid/anchorembedding vectors on every item. Those vectors are needed on the live profile for similarity matching but are dead weight in changelog history, souser-profiles.dbbloats far beyond the actual profile content.Impact
user-prompts.dbgrows without bound.Suggested fix
In
buildUserAnalysisContext, skip analysis prompts and cap each embedded prompt:Broaden the persist-time guard so the analysis prompt is never saved (match
# User Profile Analysis, or check beforesavePrompt).Cap total assembled prompt size and strip image data URLs from stored content.
Strip
centroid/anchor(embedding fields) fromprofile_data_snapshotbefore persisting a changelog entry.Workaround
(Back up
user-prompts.dbfirst.)Environment