thedotmack/claude-mem · error
Refusing awareness write outside agent memory/log
Error message
Refusing awareness write outside agent memory/log
What it means
assertSafeAwarenessLogPath() validates that awareness writes from the Grok bot pusher stay inside the agent's own memory/log directory (agentDataRoot/agents/<agentId>/memory/log). It resolves both paths and throws if the target escapes that root, preventing awareness appends from touching arbitrary filesystem locations.
Solutions
- Build the log path as path.join(agentDataRoot, 'agents', agentId, 'memory', 'log', filename) so it is anchored in the expected root.
- Verify the agentId used to compute the path matches the agentId passed to notifyGrokBotAwareness.
- Strip or reject any ../ traversal segments from the logPath before calling.
Example fix
// before: path not anchored to the agent's memory/log const logPath = path.join(agentDataRoot, 'agents', rel); // after const logPath = path.join(agentDataRoot, 'agents', agentId, 'memory', 'log', 'awareness.md');
Defensive patterns
Strategy: validation
Validate before calling
import path from 'path';
function isInsideAgentLogRoot(agentDataRoot: string, agentId: string, logPath: string): boolean {
const expectedRoot = path.resolve(path.join(agentDataRoot, 'agents', agentId, 'memory', 'log'));
const resolved = path.resolve(logPath);
return resolved === expectedRoot || resolved.startsWith(expectedRoot + path.sep);
} Try / catch
try {
notifyGrokBotAwareness(agentDataRoot, agentId, logPath, line);
} catch (err) {
if (err instanceof Error && err.message.includes('outside agent memory/log')) {
// rebuild logPath from agentDataRoot/agents/<agentId>/memory/log and retry
} else throw err;
} Prevention
- Construct awareness log paths with path.join(agentDataRoot, 'agents', agentId, 'memory', 'log', ...).
- Reject '..' segments in any user-influenced path component.
- Keep agentId consistent between path building and the pusher call.
When it happens
Trigger: notifyGrokBotAwareness() calls assertSafeAwarenessLogPath(agentDataRoot, agentId, logPath) with a logPath that resolves outside the per-agent memory/log dir — e.g. path built with ../ segments, an absolute path elsewhere, or an agentId that does not match the one baked into the log path.
Common situations: Caller constructs the log path from concatenated IDs or user-supplied agent names; agentId renamed/migrated so the stored log path no longer matches; relative vs absolute path mixing; symlinks resolving outside the root.
Understand the failure class
Background: Path traversal blocked: "path escapes the workspace" and "outside site root" errors when a path will not stay inside its allowed directory — this error's family across 26 libraries.
Related errors
- Refusing CCS Align write outside the seat-owned ccs-align…
- Rejected path traversal attempt in watch.context.path
- INVALID_CORPUS_NAME
- Refusing awareness write to profile.md
- Refusing CCS Align write to profile.md
AI-assisted analysis of thedotmack/claude-mem@d8bc9755e7 (2026-09-17).
Data as JSON: /api/errors/9ea275a7a90f3867.
Report an issue: GitHub.
Appendix: source
Thrown at src/services/integrations/GrokBotAwarenessPusher.ts:101
if (line.length <= MAX_LINE_CHARS) return line;
return `${line.slice(0, MAX_LINE_CHARS - 1)}…`;
}
export function awarenessLineBody(line: string): string {
const idx = line.indexOf(AWARENESS_TAG);
return idx >= 0 ? line.slice(idx).trim() : line.trim();
}
export function grokBotAwarenessLogPath(agentDataRoot: string, agentId: string, now: Date = new Date()): string {
const yearMonth = now.toISOString().slice(0, 7);
return path.join(agentDataRoot, 'agents', agentId, 'memory', 'log', `${yearMonth}.md`);
}
function assertSafeAwarenessLogPath(agentDataRoot: string, agentId: string, logPath: string): void {
const expectedRoot = path.resolve(path.join(agentDataRoot, 'agents', agentId, 'memory', 'log'));
const resolved = path.resolve(logPath);
if (!resolved.startsWith(expectedRoot + path.sep) && resolved !== expectedRoot) {
throw new Error('Refusing awareness write outside agent memory/log');
}
if (path.basename(resolved) === 'profile.md') {
throw new Error('Refusing awareness write to profile.md');
}
}
export function appendAwarenessLineAtomic(logPath: string, line: string): boolean {
const dir = path.dirname(logPath);
mkdirSync(dir, { recursive: true });
const existing = existsSync(logPath) ? readFileSync(logPath, 'utf8') : '';
const incomingBody = awarenessLineBody(line);
const alreadyPresent = existing
.split('\n')
.some(existingLine => existingLine.trim() && awarenessLineBody(existingLine) === incomingBody);
if (alreadyPresent) {
return false;
}View on GitHub (pinned to d8bc9755e7)