nanocoai/nanoclaw · warning
Failed to append task run log
Error message
Failed to append task run log
What it means
A task_log message targeted a task thread but appendRunLog failed to write to the group's run log file. The log line is lost; the task itself continues.
Source
Thrown at src/delivery.ts:318
const content = JSON.parse(msg.content);
// System actions — handle internally (cli_request, etc.)
if (msg.kind === 'system') {
await handleSystemAction(content, session);
return;
}
// Task-run log: the runner mirrors a run's final text here (one-door
// delivery — final text never reaches a channel; the send_message tool is
// the only delivery path from a task session). Append to the series log,
// never deliver. The caller marks it delivered so it isn't retried.
if (msg.kind === 'task_log') {
if (session.messaging_group_id === null && isTaskThread(session.thread_id) && session.thread_id) {
const series = session.thread_id.slice(`${TASKS_SYSTEM_THREAD_ID}:`.length);
try {
await appendRunLog(session.agent_group_id, series, typeof content.text === 'string' ? content.text : '');
} catch (err) {
log.warn('Failed to append task run log', { id: msg.id, sessionId: session.id, err });
}
} else {
log.warn('task_log row outside a task session — ignoring', { id: msg.id, sessionId: session.id });
}
return;
}
// Agent-to-agent — route to target session via the agent-to-agent module.
// Guarded by the channel_type check. If the module isn't installed the
// `agent_destinations` table won't exist and `routeAgentMessage`'s permission
// check will throw, which falls into the normal retry → mark-failed path.
if (msg.channelType === 'agent') {
if (!(await hasTable(getDb(), 'agent_destinations'))) {
throw new Error(`agent-to-agent module not installed — cannot route message ${msg.id}`);
}
const { routeAgentMessage } = await import('./modules/agent-to-agent/agent-route.js');
await routeAgentMessage(
{View on GitHub (pinned to 294ef2aee8)
Solutions
- Check the group folder path exists and is writable by the host user
- Free disk space if full
- Verify task run-log destination via `ncl tasks get`
- Task output is also in messages_out — regenerate the log if needed
Defensive patterns
Strategy: try-catch
Validate before calling
import fs from 'node:fs'; fs.accessSync(groupDir, fs.constants.W_OK); // verify before task runs
Try / catch
try { await appendRunLog(...); } catch { /* keep task output in messages_out as source of truth */ } Prevention
- Keep group directories writable by the host user
- Monitor disk space
- Treat messages_out as canonical; run logs are derived
When it happens
Trigger: appendRunLog throws — run-log file or its directory is unwritable/missing, disk full, or path issues in groups/<folder>/.
Common situations: Group folder perms changed, disk full, or the group directory was moved/deleted out from under the host.
Related errors
- invalid task id: ${series}
- Unknown provider: ${name}. Registered: ${known}
- engage_mode '${w.engage_mode}' can never engage on channel '
- MissingChannelAdapterError(channelType, instance)
- chat-sdk bridge instance ${JSON.stringify(config.instance)}
AI-assisted analysis of nanocoai/nanoclaw@294ef2aee8 (2026-08-28).
Data as JSON: /api/errors/49d1beafe6cf05c5.
Report an issue: GitHub.