{"record":{"id":"6fc30371b202e47e","repo":"NousResearch/hermes-agent","slug":"res-message-archive-failed","errorCode":null,"errorMessage":"${res.message || 'Archive failed'}","messagePattern":"\\$\\{res\\.message \\|\\| 'Archive failed'\\}","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"apps/desktop/src/app/learning/archive-skill-confirm-dialog.tsx","lineNumber":16,"sourceCode":"import { ConfirmDialog } from '@/components/ui/confirm-dialog'\nimport { deleteLearningNode } from '@/hermes'\nimport { type Translations, useI18n } from '@/i18n'\nimport { notify } from '@/store/notifications'\n\nexport const ARCHIVE_SKILL_DESCRIPTION = 'The skill is archived and can be restored with `hermes curator restore`.'\n\nexport function notifySkillArchived(t: Translations): void {\n  notify({ kind: 'success', message: t.skills.skillArchivedMessage, title: t.skills.skillArchivedTitle })\n}\n\nexport async function archiveLearningSkill(id: string): Promise<void> {\n  const res = await deleteLearningNode(id)\n\n  if (!res.ok) {\n    throw new Error(res.message || 'Archive failed')\n  }\n}\n\n/** Fire-and-forget a mutation whose UI already applied optimistically; a failure just rolls it back + reports. */\nexport function fireOptimistic(action: Promise<void>, rollback: () => void, onFailure: (err: unknown) => void): void {\n  void action.catch(err => {\n    rollback()\n    onFailure(err)\n  })\n}\n\ninterface ArchiveSkillConfirmDialogProps {\n  /** Apply optimistic UI updates; return rollback if the background archive fails. */\n  onApply: () => () => void\n  onClose: () => void\n  onFailure?: (err: unknown, skillName: string) => void\n  onSuccess?: () => void\n  open: boolean","sourceCodeStart":1,"sourceCodeEnd":34,"githubUrl":"https://github.com/NousResearch/hermes-agent/blob/c896c09c42910c584c4c7d2325b58c14713ea42c/apps/desktop/src/app/learning/archive-skill-confirm-dialog.tsx#L1-L34","documentation":"Thrown by archiveLearningSkill in the desktop learning module after deleteLearningNode(id) returns a non-ok response. The IPC/backend call that archives (deletes) a learned skill node failed; the error either carries the backend's message or falls back to the generic 'Archive failed'. It exists so the confirm-dialog flow can roll back the optimistic UI removal and notify the user.","triggerScenarios":"Confirming the archive-skill dialog while the backend session/IPC connection is down, the node id no longer exists (already archived elsewhere), a permission/FS error deleting the skill in ~/.hermes/skills, or the backend returning an error payload with empty message.","commonSituations":"Backend restarted mid-operation; the same skill archived from another surface (CLI `hermes curator archive`) racing the desktop action; read-only HERMES_HOME; learning DB schema drift after an upgrade.","solutions":["Check the backend/gateway log for the underlying delete error at the timestamp of the failure.","Verify the skill/node still exists and is not already archived (`hermes curator status`, then retry).","Ensure HERMES_HOME is writable and not locked by another process.","Restart the backend and retry once; if the id is stale, refresh the learning list before archiving."],"exampleFix":"// before\nif (!res.ok) {\n  throw new Error(res.message || 'Archive failed')\n}\n\n// after — include the node id to make support triage possible\nif (!res.ok) {\n  throw new Error(res.message || `Archive failed (node ${id})`)\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  await archiveLearningSkill(id)\n} catch (error) {\n  rollbackOptimisticRemoval()\n  notify({ kind: 'error', message: error instanceof Error ? error.message : 'Archive failed' })\n}","preventionTips":["Use the fireOptimistic rollback helper so UI never desyncs from backend state","Check curator/skill state before archiving (already-archived ids fail)","Watch backend logs when archive fails repeatedly — the message is often empty"],"tags":["desktop","learning","skills","ipc","curator"],"backgroundTag":null,"analyzedSha":"c896c09c42910c584c4c7d2325b58c14713ea42c","analyzedAt":"2026-08-14T17:18:01.089Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}