hoppscotch/hoppscotch · error · SyntaxError
[Hoppscotch] '${reservedConflict}' is reserved by Hoppscotch
Error message
[Hoppscotch] '${reservedConflict}' is reserved by Hoppscotch's script wrapper and cannot be used as an import binding. Please rename the import. What it means
Thrown during script combination when an import binding name collides with a name reserved by Hoppscotch's script wrapper internals. The reserved set is { '__hoppReporter', 'globalThis' } — the former is the reporter function injected by the wrapper to surface test results to the host, and the latter is read for the reporter at module scope. Importing these would cause a duplicate-declaration or shadowing error post-hoist, so the pre-cage check catches it early.
Source
Thrown at packages/hoppscotch-js-sandbox/src/utils/scripting.ts:241
if (fns.length === 0 && allImports.length === 0 && !parseError) return ""
// Errors short-circuit before synthesis; reserved-name check sits before
// the import-only return so reserved bindings still surface.
if (parseError !== undefined) {
return synthesizeReporterWrapper(
`throw new SyntaxError(${JSON.stringify(`[Hoppscotch] Script failed to parse: ${parseError}`)});`
)
}
if (conflictingName !== undefined) {
return synthesizeReporterWrapper(
`throw new SyntaxError(${JSON.stringify(`[Hoppscotch] '${conflictingName}' is imported from different sources across scripts in this request's chain. Please import it from a single source, or rename one of the imports to resolve the conflict.`)});`
)
}
if (reservedConflict !== undefined) {
return synthesizeReporterWrapper(
`throw new SyntaxError(${JSON.stringify(`[Hoppscotch] '${reservedConflict}' is reserved by Hoppscotch's script wrapper and cannot be used as an import binding. Please rename the import.`)});`
)
}
// Import-only cascade: skip the try/catch — no awaited bodies to route
// errors from. Module-evaluation errors propagate via faraday-cage.
if (fns.length === 0) return allImports.join("\n")
// Wrap the awaited chain in try/catch so top-level throws / rejected
// awaits reach the host reporter; faraday-cage otherwise swallows
// async-boundary errors via its keepAlive loop.
const body = fns.map((fn) => `await (${fn})();`).join("\n")
const tryBlock = synthesizeReporterWrapper(body)
if (allImports.length === 0) return tryBlock
return [allImports.join("\n"), tryBlock].join("\n")
}
View on GitHub (pinned to 1acb8a3a75)
Solutions
- Rename the import binding using `as`: `import { __hoppReporter as myReporter } from 'somelib'`.
- If you imported globalThis, use a namespace import instead: `import * as gt from 'somelib'`.
- Avoid copying Hoppscotch internal symbols into user scripts — they are not part of the public API.
Example fix
// before
import { globalThis } from './shim'
// after — rename the binding
import { globalThis as gtShim } from './shim' Defensive patterns
Strategy: type-guard
Validate before calling
// Check if any import binding collides with reserved names
const RESERVED = new Set(['__hoppReporter', 'globalThis'])
function findReservedConflicts(scripts) {
const importRegex = /import\s+(?:\{([^}]+)\}|(\w+))(?:\s*,\s*\{([^}]+)\})?\s+from/g
const conflicts = []
for (const script of scripts) {
let match
while ((match = importRegex.exec(script)) !== null) {
const names = (match[1] || match[3] || '')
.split(',')
.map(s => s.trim().split(' as ')[0].trim())
.filter(Boolean)
if (match[2]) names.push(match[2])
for (const name of names) {
if (RESERVED.has(name)) conflicts.push(name)
}
}
}
return conflicts
}
const conflicts = findReservedConflicts(scripts)
if (conflicts.length > 0) {
console.error('Reserved name conflicts:', conflicts)
} Type guard
const RESERVED_WRAPPER_NAMES = new Set(['__hoppReporter', 'globalThis'])
function isReservedImportName(name) {
return RESERVED_WRAPPER_NAMES.has(name)
} Try / catch
// The SyntaxError is thrown inside the sandbox and surfaced via the host reporter
try {
const results = await runSandboxScripts(scripts)
const reservedError = results.errors?.find(e => e.message.includes('reserved by Hoppscotch'))
if (reservedError) {
console.error(reservedError.message)
// Rename the binding in the offending script
}
} catch (e) {
console.error('Script error:', e.message)
} Prevention
- Never name an import binding __hoppReporter or globalThis.
- If a library exports these names, rename with `as` at the import site.
- Avoid copying Hoppscotch internal source into user scripts.
- Use namespace imports to avoid any name-level collision with internals.
When it happens
Trigger: A script contains `import { __hoppReporter } from 'somelib'` or `import { globalThis } from 'somelib'`. The binding name matches one of the two reserved identifiers, triggering this error before the script reaches the sandbox evaluator.
Common situations: A library happens to export a member named 'globalThis' (unlikely but possible with JS interop shims), or a user manually names an import '__hoppReporter' (e.g., copying internal Hoppscotch source code into a test script). This is rare in practice but the guard prevents a confusing post-hoist SyntaxError.
Related errors
- [Hoppscotch] '${conflictingName}' is imported from different
- [Hoppscotch] Script failed to parse: ${parseError}
- JSON Schema validation failed: ${error}
- charset() expects a string value (typically Content-Type hea
- Expected charset "${expectedCharset}" not found in "${expect
AI-assisted analysis of hoppscotch/hoppscotch@1acb8a3a75 (2026-08-12).
Data as JSON: /api/errors/6ffe5c70b4363533.
Report an issue: GitHub.