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: booleanView on GitHub (pinned to c896c09c42)
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.
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
- 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
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
- gh pr create failed (is gh installed and authenticated?)
- Branch name is required.
- Missing URL
- Invalid external URL
- Invalid preview URL
AI-assisted analysis of NousResearch/hermes-agent@c896c09c42 (2026-08-14).
Data as JSON: /api/errors/6fc30371b202e47e.
Report an issue: GitHub.