{"record":{"id":"af5b644d5c78c193","repo":"Budibase/budibase","slug":"user-script-error","errorCode":"USER_SCRIPT_ERROR","errorMessage":"error while running user-supplied JavaScript: ${userScriptError.toString()}","messagePattern":"error while running user-supplied JavaScript: (.+?)","errorType":"exception","errorClass":"UserScriptError","httpStatus":null,"severity":"error","filePath":"packages/server/src/jsRunner/vm/isolated-vm.ts","lineNumber":206,"sourceCode":"      try {\n        results = {}\n        results['${this.runResultKey}']=${this.codeWrapper(code)}\n      } catch (e) {\n        results['${this.runErrorKey}']=e\n      }\n    `\n\n    const script = this.isolate.compileScriptSync(code)\n\n    script.runSync(this.vm, { timeout: this.invocationTimeout, release: false })\n    new Promise(() => {\n      script.release()\n    })\n\n    // We can't rely on the script run result as it will not work for non-transferable values\n    const result = this.getFromContext(this.resultKey)\n    if (result[this.runErrorKey]) {\n      throw new UserScriptError(result[this.runErrorKey])\n    }\n    return result[this.runResultKey]\n  }\n\n  close(): void {\n    this.vm.release()\n    this.isolate.dispose()\n  }\n\n  private registerCallbacks(functions: Record<string, any>) {\n    const libId = crypto.randomUUID().replace(/-/g, \"\")\n\n    const x: Record<string, string> = {}\n    for (const [funcName, func] of Object.entries(functions)) {\n      const key = `f${libId}${funcName}cb`\n      x[funcName] = key\n\n      this.addToContext({","sourceCodeStart":188,"sourceCodeEnd":224,"githubUrl":"https://github.com/Budibase/budibase/blob/a81a902e9a8fe55b467d106765f6638f12e35c49/packages/server/src/jsRunner/vm/isolated-vm.ts#L188-L224","documentation":"The isolated-vm JS runner wraps user-supplied JavaScript in a try/catch inside the V8 isolate. Any error the user's script throws (or which comes from the script's own logic/callbacks) is captured and re-thrown on the host side as a UserScriptError after execution, distinguishing user mistakes from host infrastructure failures.","triggerScenarios":"Calling execute(code) where the user JavaScript throws at runtime: undefined variable access, type errors, a registered callback function rejects/throws, or bson conversion fails. The isolate itself ran fine; the script errored.","commonSituations":"Builders write JS bindings in automations/queries that reference missing row fields, call helper functions with wrong arguments, or use APIs not available in the sandbox. CPU-time limit breaches throw a different error (JsRequestTimeoutError), not this one.","solutions":["Read the embedded userScriptError message - it is the original error from inside the sandbox; fix the user JS accordingly.","Verify all referenced variables/fields exist and are defined before the script runs (null-check row/data inputs).","Test the snippet in a plain Node REPL with mocked inputs to reproduce the error outside the isolate.","If a registered callback throws, fix the callback implementation on the host side rather than the script."],"exampleFix":"// before\nreturn data.rows[0].value * 2\n// after\nreturn data.rows && data.rows[0] ? data.rows[0].value * 2 : 0","handlingStrategy":"try-catch","validationCode":"if (typeof userCode !== \"string\" || !userCode.trim()) throw new Error(\"Empty script\")","typeGuard":"const isUserScriptError = (e: unknown): e is UserScriptError => e instanceof UserScriptError","tryCatchPattern":"try {\n  const result = runner.execute(code)\n} catch (e) {\n  if (e instanceof UserScriptError) {\n    // surface e.message to the user as a script problem, not a server fault\n  } else {\n    throw e\n  }\n}","preventionTips":["Null-check all input data referenced in the script before execution","Keep scripts trivially simple; move complex logic into server-side helpers","Test snippets outside the sandbox with mocked inputs","Log the full UserScriptError message - it contains the original sandbox error"],"tags":["javascript","sandbox","user-input"],"backgroundTag":"user-script-runtime-error","analyzedSha":"a81a902e9a8fe55b467d106765f6638f12e35c49","analyzedAt":"2026-08-29T01:03:10.972Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}