NousResearch/hermes-agent · error · Error
Could not write artifact file
Error message
Could not write artifact file
What it means
Thrown by openHtmlInBrowser in the desktop artifact preview after calling bridge.saveImageBuffer(bytes, '.html') and receiving a falsy return. The Electron main-side handler writes the buffer to a temp file and returns its path; an empty/undefined path means the write failed or the handler rejected softly (e.g. temp dir not writable, IPC handler error swallowed, disk full). The renderer treats 'no path' as 'artifact file could not be created' and refuses to build a file:// URL from nothing.
Source
Thrown at apps/desktop/src/app/chat/right-rail/preview-artifact.tsx:60
'</body></html>'
].join('\n')
}
/** Write the composed document to a real temp file through the existing
* buffer-save IPC, then hand it to the OS browser. A blob/data URL can't
* cross into the OS default browser, so a file on disk is the honest path. */
async function openHtmlInBrowser(content: string): Promise<void> {
const bridge = window.hermesDesktop
if (!bridge?.saveImageBuffer || !bridge.openExternal) {
throw new Error('Desktop bridge unavailable')
}
const bytes = new TextEncoder().encode(composeArtifactHtml(content))
const path = await bridge.saveImageBuffer(bytes, '.html')
if (!path) {
throw new Error('Could not write artifact file')
}
const fileUrl = `file://${path.startsWith('/') ? '' : '/'}${path.replace(/\\/g, '/')}`
if (bridge.openPreviewInBrowser) {
await bridge.openPreviewInBrowser(fileUrl)
return
}
await bridge.openExternal(fileUrl)
}
/**
* Live view for renderable artifact content.
*
* HTML runs in an `<iframe sandbox="allow-scripts">` — scripts execute in an
* opaque origin with no same-origin access, no top navigation, no popups, noView on GitHub (pinned to c896c09c42)
Solutions
- Check that the OS temp directory is writable and has free space (echo $TMPDIR; df -h /tmp).
- Inspect the Electron main process log for an exception in the saveImageBuffer IPC handler and fix that root cause.
- Restart/reinstall the desktop app if the preload/main bundle versions drifted.
- As a developer: make the main-side handler return an error message instead of undefined so the renderer can show the real cause.
Example fix
// before
const path = await bridge.saveImageBuffer(bytes, '.html')
if (!path) {
throw new Error('Could not write artifact file')
}
// after (main-side handler surfaces the failure)
const path = await bridge.saveImageBuffer(bytes, '.html')
if (!path) {
throw new Error('Could not write artifact file (check temp dir permissions and free space)')
} Defensive patterns
Strategy: try-catch
Try / catch
let path: string
try {
path = await bridge.saveImageBuffer(bytes, '.html')
} catch (ipcError) {
throw new Error(`Artifact write IPC failed: ${String(ipcError)}`)
}
if (!path) {
throw new Error('Could not write artifact file (temp dir unwritable or full)')
} Prevention
- Monitor free space in TMPDIR on user machines
- Make the main-side saveImageBuffer handler return {path} or {error} explicitly instead of undefined
- Distinguish IPC rejection (catch) from soft undefined return (falsy check) in diagnostics
When it happens
Trigger: Invoking 'open artifact in browser' when the OS temp directory is not writable or full, when the saveImageBuffer IPC handler threw on the main side and resolved undefined, or when a sandboxed renderer passes a buffer the main process cannot serialize.
Common situations: Disk-full or TMPDIR pointing to a read-only location inside dev containers; main-process exception in the temp-file writer after an Electron upgrade changed dialog/fs APIs; permission restrictions on macOS with hardened runtime denying temp writes.
Related errors
- Could not create directory: ${error.message}
- Invalid rename
- "${name}" already exists
- Invalid path
- Content too large
AI-assisted analysis of NousResearch/hermes-agent@c896c09c42 (2026-08-14).
Data as JSON: /api/errors/df71352aa7450d17.
Report an issue: GitHub.