different-ai/openwork · error · InterpreterRuntimeError
${ref.name} received malformed URI data: ${error instanceof
Error message
${ref.name} received malformed URI data: ${error instanceof Error ? error.message : String(error)} What it means
encodeURI/decodeURI/encodeURIComponent/decodeURIComponent are wrapped so malformed input surfaces as a sandbox URIError with a clear message. The host throws when decoding invalid escape sequences (e.g. a stray %) or encoding lone surrogates; the wrapper rethrows it tagged as URIError with the original message.
Source
Thrown at packages/codemode/src/stdlib/url.ts:61
])
export const uriArgument = (value: unknown, label: string): string => coerceToString(boundedData(value, label))
export const invokeUriFunction = (ref: UriFunction, args: Array<unknown>, node: AstNode): string => {
const value = uriArgument(args[0], `${ref.name} input`)
try {
switch (ref.name) {
case "encodeURI":
return encodeURI(value)
case "encodeURIComponent":
return encodeURIComponent(value)
case "decodeURI":
return decodeURI(value)
case "decodeURIComponent":
return decodeURIComponent(value)
}
} catch (error) {
throw new InterpreterRuntimeError(
`${ref.name} received malformed URI data: ${error instanceof Error ? error.message : String(error)}`,
node,
).as("URIError")
}
}
export const urlArgument = (value: unknown, label: string): string =>
value instanceof SandboxURL ? value.url.href : uriArgument(value, label)
export const invokeURLStatic = (name: string, args: Array<unknown>, node: AstNode): unknown => {
if (!urlStatics.has(name)) throw new InterpreterRuntimeError(`URL.${name} is not available in CodeMode.`, node)
if (args.length === 0) throw new InterpreterRuntimeError(`URL.${name} requires a URL argument.`, node).as("TypeError")
const input = urlArgument(args[0], `URL.${name} input`)
const base = args[1] === undefined ? undefined : urlArgument(args[1], `URL.${name} base`)
try {
const url = new URL(input, base)
return name === "canParse" ? true : new SandboxURL(url)
} catch {View on GitHub (pinned to 2b7df46e8a)
Solutions
- Validate/escape % as %25 before decoding user input.
- Wrap decode in try/catch and fall back to the raw value on failure.
- Ensure encoded strings are not split in the middle of a %XX sequence (decode before slicing).
- Replace lone surrogates or use well-formed string handling before encodeURI.
Example fix
// before
const decoded = decodeURIComponent(raw) // raw may contain "%"
// after
const decoded = raw.includes("%") ? decodeURIComponent(raw.replace(/%(?![0-9A-Fa-f]{2})/g, "%25")) : raw Defensive patterns
Strategy: try-catch
Validate before calling
const safeDecode = (s) => typeof s === "string" && !/%(?![0-9A-Fa-f]{2})/.test(s) ? decodeURIComponent(s) : s Try / catch
try { out = decodeURIComponent(raw) } catch (e) { out = raw /* or log + fallback */ } Prevention
- Escape bare % before decoding untrusted input
- Decode before splitting/slicing strings
- Check for lone surrogates before encodeURI
When it happens
Trigger: `decodeURIComponent("%")` or `decodeURIComponent("%E0%A4%A")` (truncated/invalid percent-escape); `encodeURI("\uD800")` (lone surrogate).
Common situations: Decoding user-supplied or third-party query strings that contain raw % characters; splitting an encoded string mid-escape before decoding; handling binary data chopped at arbitrary byte boundaries.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- String method '${name}' is not available in CodeMode.
- Array.from(...) does not support a map function in CodeMode;
- Array.from expects an array, string, Map, Set, or array-like
- Array.${name} is not available in CodeMode.
- console.${ref.name} is not available in CodeMode.
AI-assisted analysis of different-ai/openwork@2b7df46e8a (2026-09-01).
Data as JSON: /api/errors/b9521a347bbd705c.
Report an issue: GitHub.