NousResearch/hermes-agent · warning · Error

c.couldNotPreview(attachment.label)

Error message

c.couldNotPreview(attachment.label)

What it means

Thrown in the desktop chat composer's attachment preview handler (attachments.tsx). After the user asks to preview an attachment target (a path or URL extracted from the attachment), normalizeOrLocalPreviewTarget resolves it against the session cwd; if resolution yields nothing usable (no local file, no reachable URL), the code throws a localized 'could not preview <label>' error instead of silently doing nothing. The surrounding catch shows an error notification, so this is a user-facing 'preview target unresolvable' signal, not a crash.

Source

Thrown at apps/desktop/src/app/chat/composer/attachments.tsx:98

    const rawTarget =
      attachment.path ||
      attachment.detail ||
      attachment.refText?.replace(/^@(file|image|url):/, '') ||
      attachment.label ||
      ''

    const target = rawTarget.replace(/^`|`$/g, '')

    if (!target) {
      return
    }

    try {
      const preview = await normalizeOrLocalPreviewTarget(target, cwd || undefined)

      if (!preview) {
        throw new Error(c.couldNotPreview(attachment.label))
      }

      openPreview(preview, 'manual')
    } catch (error) {
      notifyError(error, c.previewUnavailable)
    }
  }

  return (
    <>
      <Tip label={attachment.path || attachment.detail || attachment.label}>
        <div className="group/attachment relative min-w-0 shrink-0">
          <button
            aria-busy={isUploading || undefined}
            aria-label={canPreview ? c.previewLabel(attachment.label) : attachment.label}
            className={cn(
              'flex max-w-56 items-center gap-2 rounded-2xl border bg-background/50 px-2 py-1.5 text-left shadow-[inset_0_1px_0_rgba(255,255,255,0.18)] transition-colors disabled:cursor-default',
              hasUploadError

View on GitHub (pinned to c896c09c42)

Solutions

  1. Verify the attachment path exists locally (or on the machine the preview resolver runs on) and that the session cwd is correct.
  2. If the backend is remote, mount/sync the backend filesystem or use a target the resolver supports (absolute local path or http(s) URL).
  3. For developers: check normalizeOrLocalPreviewTarget's accepted schemes and make the attachment carry an absolute path or explicit cwd.
  4. Update a stale attachment payload — re-attach the file instead of previewing a dangling reference.

Example fix

// before
const preview = await normalizeOrLocalPreviewTarget(target, cwd || undefined)
if (!preview) {
  throw new Error(c.couldNotPreview(attachment.label))
}

// after — give the resolver a real anchor and surface why it failed
const preview = await normalizeOrLocalPreviewTarget(
  attachment.path?.startsWith('/') ? attachment.path : joinPath(cwd, target),
  cwd || undefined
)
if (!preview) {
  throw new Error(c.couldNotPreview(attachment.path || attachment.label))
}
Defensive patterns

Strategy: try-catch

Validate before calling

const target = rawTarget.replace(/^`|`$/g, '')
const isPreviewable = target && (target.startsWith('/') || target.startsWith('http'))
if (!isPreviewable) return  // don't attempt preview for unanchorable targets

Type guard

const isPreviewableTarget = (t: string | undefined): t is string =>
  Boolean(t) && (/^https?:\/\//.test(t!) || t!.startsWith('/') || t!.startsWith('~'))

Try / catch

try {
  const preview = await normalizeOrLocalPreviewTarget(target, cwd || undefined)
  if (!preview) throw new Error(c.couldNotPreview(attachment.label))
  openPreview(preview, 'manual')
} catch (error) {
  // surfaced as toast, not a crash — keep it that way
  notifyError(error, c.previewUnavailable)
}

Prevention

When it happens

Trigger: Clicking preview/open on an attachment whose target is a remote path from another machine (SSH-backed session), a path that no longer exists (file deleted or cwd changed), a bare filename that normalizeOrLocalPreviewTarget cannot anchor to the supplied cwd, or a URL scheme the preview normalizer rejects.

Common situations: Desktop app connected to a remote backend over URL+token where attachment paths refer to the backend's filesystem, not the local one; sessions resumed after the working directory moved; attachment metadata produced by an older schema where path/detail fields are empty.

Related errors


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