NousResearch/hermes-agent · error

unsupported import${unsupported.length > 1 ? 's' : ''}: ${un

Error message

unsupported import${unsupported.length > 1 ? 's' : ''}: ${unsupported.join(', ')} — runtime plugins may only import @hermes/plugin-sdk and react

What it means

Thrown by the runtime-plugin loader (runtime-loader.ts:123) when the plugin source imports bare specifiers that are not `@hermes/plugin-sdk` or `react*`. The loader rewrites only the SDK shim imports to blob URLs before dynamic import(); any other bare specifier (npm package name) cannot resolve inside a blob module, so the loader fails fast with a readable list instead of the cryptic native 'Failed to resolve module specifier' error. Relative imports (./ ../), absolute paths, and URL-scheme imports are allowed through by unsupportedImports().

Source

Thrown at apps/desktop/src/contrib/runtime-loader.ts:123

}

/** Evaluate + register one runtime plugin. Returns its id, or null on failure. */
export async function loadRuntimePlugin(
  source: string,
  origin: string,
  options: LoadOptions = {}
): Promise<null | string> {
  installPluginSdk()

  try {
    if (options.integrity && !(await verifyIntegrity(source, options.integrity))) {
      throw new Error(`integrity check failed for ${origin}`)
    }

    const unsupported = unsupportedImports(source)

    if (unsupported.length > 0) {
      throw new Error(
        `unsupported import${unsupported.length > 1 ? 's' : ''}: ${unsupported.join(', ')} — ` +
          `runtime plugins may only import @hermes/plugin-sdk and react`
      )
    }

    const url = URL.createObjectURL(new Blob([rewriteSpecifiers(source)], { type: 'text/javascript' }))

    let mod: { default?: HermesPlugin }

    try {
      mod = await import(/* @vite-ignore */ url)
    } finally {
      URL.revokeObjectURL(url)
    }

    const plugin = mod.default

    if (!plugin?.id || typeof plugin.register !== 'function') {

View on GitHub (pinned to c896c09c42)

Solutions

  1. Remove the bare import and inline the needed helper code into plugin.js, or reimplement it via `@hermes/plugin-sdk` and `react` only.
  2. If the dependency is pure data or small, vendor it as a relative file (`./dep.js`) next to plugin.js and import it relatively.
  3. If it must be a package, convert it into part of the SDK surface (@hermes/plugin-sdk) so the loader maps it — a core change, not a plugin change.
  4. Re-read the error's list: every named specifier must go, the error enumerates all offenders at once.

Example fix

// before
import { debounce } from 'lodash-es'
import { useEffect } from 'react'

// after
import { useEffect } from 'react'
function debounce(fn: (...a: unknown[]) => void, ms: number) { /* inlined */ }
Defensive patterns

Strategy: validation

Validate before calling

const ALLOWED_BARE = new Set(['@hermes/plugin-sdk'])
function badImports(source: string): string[] {
  const re = /(from\s*|import\s*\(\s*|import\s+)(['"])([^'"]+)\2/g
  const bad = new Set<string>()
  for (const m of source.matchAll(re)) {
    const spec = m[3]!
    if (!/^[./]/.test(spec) && !/^[a-z][a-z0-9+.-]*:/i.test(spec) && !ALLOWED_BARE.has(spec) && !/^react/.test(spec)) bad.add(spec)
  }
  return [...bad]
}
if (badImports(pluginSource).length) rejectPlugin('inline or drop: ' + badImports(pluginSource).join(', '))

Try / catch

try { await loadRuntimePlugin(src, origin) } catch (e) { if (e instanceof Error && e.message.startsWith('unsupported import')) { /* list the named specifiers, inline them, retry */ } }

Prevention

When it happens

Trigger: A plugin.js containing `import lodash from 'lodash'`, `import { foo } from '@hermes/other-thing'`, or a side-effect `import 'some-polyfill'`; a dynamic `import('uuid')` inside the plugin; any bare npm-style specifier not present in sdkImportMap().

Common situations: Porting an npm module or a bundled React component into a desktop plugin without inlining dependencies; the agent generating a plugin that pulls in a utility library by habit; version drift where a previously-mapped specifier is removed from the SDK shim map.

Related errors


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