{"record":{"id":"1b0b41a951fe4f0a","repo":"different-ai/openwork","slug":"the-right-hand-side-of-instanceof-must-be-a-cons","errorCode":null,"errorMessage":"The right-hand side of 'instanceof' must be a constructor CodeMode knows: Error (or a specific error type like TypeError), Date, RegExp, Map, Set, URL, URLSearchParams, Array, Object, or Promise.","messagePattern":"The right-hand side of 'instanceof' must be a constructor CodeMode knows: Error \\(or a specific error type like TypeError\\), Date, RegExp, Map, Set, URL, URLSearchParams, Array, Object, or Promise\\.","errorType":"exception","errorClass":"InterpreterRuntimeError","httpStatus":null,"severity":"error","filePath":"packages/codemode/src/interpreter/runtime.ts","lineNumber":330,"sourceCode":"      case \"Set\":\n        return lhs instanceof SandboxSet\n      case \"URL\":\n        return lhs instanceof SandboxURL\n      case \"URLSearchParams\":\n        return lhs instanceof SandboxURLSearchParams\n      case \"Array\":\n        return Array.isArray(lhs)\n      case \"Object\":\n        return lhs !== null && (typeof lhs === \"object\" || typeofValue(lhs) === \"function\")\n    }\n  }\n  if (rhs instanceof PromiseNamespace) return lhs instanceof SandboxPromise\n  // Number/String/Boolean wrap primitives in JS; no boxed values exist in CodeMode, so\n  // `x instanceof Number` is always false - exactly what it is for primitives in JS.\n  if (rhs instanceof CoercionFunction && (rhs.name === \"Number\" || rhs.name === \"String\" || rhs.name === \"Boolean\")) {\n    return false\n  }\n  throw new InterpreterRuntimeError(\n    \"The right-hand side of 'instanceof' must be a constructor CodeMode knows: Error (or a specific error type like TypeError), Date, RegExp, Map, Set, URL, URLSearchParams, Array, Object, or Promise.\",\n    node,\n  )\n}\n\nconst invokeStringMethod = (value: string, name: string, args: Array<unknown>, node: AstNode): unknown => {\n  const str = (index: number): string => {\n    const arg = args[index]\n    if (typeof arg !== \"string\")\n      throw new InterpreterRuntimeError(`String.${name} expects argument ${index + 1} to be a string.`, node)\n    return arg\n  }\n  const num = (index: number): number => {\n    const arg = args[index]\n    if (typeof arg !== \"number\")\n      throw new InterpreterRuntimeError(`String.${name} expects argument ${index + 1} to be a number.`, node)\n    return arg\n  }","sourceCodeStart":312,"sourceCodeEnd":348,"githubUrl":"https://github.com/different-ai/openwork/blob/2b7df46e8ae1517d64c896c7793d2d52ec845669/packages/codemode/src/interpreter/runtime.ts#L312-L348","documentation":"When the interpreter evaluates a binary `instanceof` expression, the right-hand side must resolve to one of a fixed allowlist of constructors that CodeMode models: Error types, Date, RegExp, Map, Set, URL, URLSearchParams, Array, Object, Promise (plus Number/String/Boolean coercion functions, which are statically false). If the RHS is any other value — undefined, a user class, a function, a sandbox value the interpreter doesn't recognize — it throws this InterpreterRuntimeError instead of silently misbehaving.","triggerScenarios":"Evaluating `x instanceof SomeClass` where SomeClass is a user-defined class or an unknown/undefined identifier inside a CodeMode script; e.g. `err instanceof MyCustomError` or `v instanceof Foo` where Foo isn't one of the supported constructors.","commonSituations":"Porting Node.js code with custom error classes into CodeMode scripts, typos in constructor names, or LLM-generated code using application-specific classes the sandbox doesn't provide.","solutions":["Rewrite the check to use the constructor's own discriminant instead of instanceof, e.g. `err.name === \"TypeError\"` or `err.message.includes(...)` for error narrowing.","Restrict instanceof to the supported constructors listed in the message (Error, TypeError, Date, RegExp, Map, Set, URL, URLSearchParams, Array, Object, Promise).","Use `Array.isArray(x)` / `typeof x` checks instead of `x instanceof Array/Object` where possible.","Register/extend the sandbox with the needed class only if you control the codemode interpreter's constructor namespace."],"exampleFix":"// before\nif (err instanceof MyCustomError) { ... }\n// after\nif (err instanceof Error && err.name === \"MyCustomError\") { ... }","handlingStrategy":"type-guard","validationCode":"const KNOWN = [\"Error\",\"TypeError\",\"RangeError\",\"Date\",\"RegExp\",\"Map\",\"Set\",\"URL\",\"URLSearchParams\",\"Array\",\"Object\",\"Promise\"]\nconst usesUnknownInstanceof = (script: string): boolean =>\n  KNOWN.some((k) => new RegExp(`instanceof\\\\s+${k}\\\\b`).test(script))\n  ? false\n  : /instanceof\\s+[A-Za-z_$]/.test(script)","typeGuard":"const isKnownConstructor = (v: unknown): boolean =>\n  v === Error || v === TypeError || v === Date || v === RegExp || v === Map || v === Set ||\n  v === URL || v === URLSearchParams || v === Array || v === Object || v === Promise","tryCatchPattern":"try {\n  await program(script)\n} catch (e) {\n  if (e instanceof Error && e.message.includes(\"right-hand side of 'instanceof'\")) {\n    // rewrite the script: replace custom-class instanceof with err.name / property checks\n  } else throw e\n}","preventionTips":["Ban `instanceof` with user-defined classes in scripts; lint generated code for it.","Narrow errors via err.name or err.message instead of custom error classes.","Prefer Array.isArray and typeof over instanceof Array/Object.","Keep a whitelist test that runs representative scripts containing each supported constructor."],"tags":["interpreter","instanceof","sandbox","unsupported-operation"],"backgroundTag":"instanceof-unsupported-constructor","analyzedSha":"2b7df46e8ae1517d64c896c7793d2d52ec845669","analyzedAt":"2026-09-01T07:59:23.713Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}