thedotmack/claude-mem · error

Refusing awareness write to profile.md

Error message

Refusing awareness write to profile.md

What it means

Within assertSafeAwarenessLogPath(), any awareness write whose target basename is profile.md is rejected outright. profile.md is a protected agent artifact managed by a different subsystem; the awareness pusher (append-only log lines) must never overwrite it, so the guard throws unconditionally on that filename.

Solutions

  1. Point the awareness write at the log file (e.g. awareness.md) instead of profile.md.
  2. Use the dedicated profile-update API for profile content rather than the awareness pusher.
  3. Add a caller-side guard: if (path.basename(logPath) === 'profile.md') skip or redirect the write.

Example fix

// before
const logPath = path.join(agentDir, 'memory', 'log', 'profile.md');

// after
const logPath = path.join(agentDir, 'memory', 'log', 'awareness.md');
Defensive patterns

Strategy: validation

Validate before calling

import path from 'path';
if (path.basename(logPath) === 'profile.md') {
  throw new Error('profile.md is protected; use the profile API');
}

Try / catch

try {
  notifyGrokBotAwareness(agentDataRoot, agentId, logPath, line);
} catch (err) {
  if (err instanceof Error && err.message.includes('profile.md')) {
    // redirect to the profile-update flow instead of the awareness pusher
  } else throw err;
}

Prevention

When it happens

Trigger: notifyGrokBotAwareness() is given a logPath ending in profile.md — e.g. an awareness key mapped to 'profile', a shared filename constant reused across features, or a caller confusing the awareness log with the profile file.

Common situations: A routing map that sends both 'profile' and 'log' events through the awareness pusher; refactored constants where AWARENESS_LOG was accidentally set to profile.md; a caller intending to update the profile via the wrong API.

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


AI-assisted analysis of thedotmack/claude-mem@d8bc9755e7 (2026-09-17). Data as JSON: /api/errors/bd8fabcb538e4f60. Report an issue: GitHub.

Appendix: source

Thrown at src/services/integrations/GrokBotAwarenessPusher.ts:104

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;
  }

  const prefix = existing.length === 0 || existing.endsWith('\n') ? existing : `${existing}\n`;
  const next = `${prefix}${line}\n`;

View on GitHub (pinned to d8bc9755e7)