NousResearch/hermes-agent · error · Error

${res.message || 'Archive failed'}

Error message

${res.message || 'Archive failed'}

What it means

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.

Source

Thrown at apps/desktop/src/app/learning/archive-skill-confirm-dialog.tsx:16

import { ConfirmDialog } from '@/components/ui/confirm-dialog'
import { deleteLearningNode } from '@/hermes'
import { type Translations, useI18n } from '@/i18n'
import { notify } from '@/store/notifications'

export const ARCHIVE_SKILL_DESCRIPTION = 'The skill is archived and can be restored with `hermes curator restore`.'

export function notifySkillArchived(t: Translations): void {
  notify({ kind: 'success', message: t.skills.skillArchivedMessage, title: t.skills.skillArchivedTitle })
}

export async function archiveLearningSkill(id: string): Promise<void> {
  const res = await deleteLearningNode(id)

  if (!res.ok) {
    throw new Error(res.message || 'Archive failed')
  }
}

/** Fire-and-forget a mutation whose UI already applied optimistically; a failure just rolls it back + reports. */
export function fireOptimistic(action: Promise<void>, rollback: () => void, onFailure: (err: unknown) => void): void {
  void action.catch(err => {
    rollback()
    onFailure(err)
  })
}

interface ArchiveSkillConfirmDialogProps {
  /** Apply optimistic UI updates; return rollback if the background archive fails. */
  onApply: () => () => void
  onClose: () => void
  onFailure?: (err: unknown, skillName: string) => void
  onSuccess?: () => void
  open: boolean

View on GitHub (pinned to c896c09c42)

Solutions

  1. Check the backend/gateway log for the underlying delete error at the timestamp of the failure.
  2. Verify the skill/node still exists and is not already archived (`hermes curator status`, then retry).
  3. Ensure HERMES_HOME is writable and not locked by another process.
  4. Restart the backend and retry once; if the id is stale, refresh the learning list before archiving.

Example fix

// before
if (!res.ok) {
  throw new Error(res.message || 'Archive failed')
}

// after — include the node id to make support triage possible
if (!res.ok) {
  throw new Error(res.message || `Archive failed (node ${id})`)
}
Defensive patterns

Strategy: try-catch

Try / catch

try {
  await archiveLearningSkill(id)
} catch (error) {
  rollbackOptimisticRemoval()
  notify({ kind: 'error', message: error instanceof Error ? error.message : 'Archive failed' })
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of NousResearch/hermes-agent@c896c09c42 (2026-08-14). Data as JSON: /api/errors/6fc30371b202e47e. Report an issue: GitHub.