{"record":{"id":"88647da8af08385d","repo":"Automattic/harper","slug":"expected-binary-to-be-a-string-of-url-but-got-ty","errorCode":null,"errorMessage":"Expected binary to be a string of url but got ${typeof binaryUrl}.","messagePattern":"Expected binary to be a string of url but got (.+?)\\.","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"packages/harper.js/src/WorkerLinter/worker.ts","lineNumber":13,"sourceCode":"/// <reference lib=\"webworker\" />\nimport './shims';\nimport { SuperBinaryModule, type WasmGlueFlavor } from '../BinaryModule';\nimport LocalLinter from '../LocalLinter';\nimport Serializer, { isSerializedRequest, type SerializedRequest } from '../Serializer';\n\n// Notify the main thread that we are ready\nself.postMessage('ready');\n\nself.onmessage = (e) => {\n\tconst [binaryUrl, dialect, glueFlavor] = e.data;\n\tif (typeof binaryUrl !== 'string') {\n\t\tthrow new TypeError(`Expected binary to be a string of url but got ${typeof binaryUrl}.`);\n\t}\n\tif (glueFlavor !== undefined && glueFlavor !== 'full' && glueFlavor !== 'slim') {\n\t\tthrow new TypeError(`Expected glue flavor to be \"full\" or \"slim\" but got ${glueFlavor}.`);\n\t}\n\tconst binary = SuperBinaryModule.create(binaryUrl, glueFlavor as WasmGlueFlavor | undefined);\n\tconst serializer = new Serializer(binary);\n\tconst linter = new LocalLinter({ binary, dialect });\n\n\tasync function processRequest(v: SerializedRequest) {\n\t\tconst { procName, args } = await serializer.deserialize(v);\n\n\t\tif (procName in linter) {\n\t\t\t// @ts-expect-error\n\t\t\tconst res = await linter[procName](...args);\n\t\t\tpostMessage(await serializer.serializeArg(res));\n\t\t}\n\t}\n","sourceCodeStart":1,"sourceCodeEnd":31,"githubUrl":"https://github.com/Automattic/harper/blob/5fe7d5ab76492d83f3ecdbc3f1da83c75dcb6f83/packages/harper.js/src/WorkerLinter/worker.ts#L1-L31","documentation":"The WorkerLinter worker script expects the first message's data array to start with a string URL pointing at the WASM binary. If e.data[0] is not a string, it throws this TypeError instead of initializing SuperBinaryModule. This validates the bootstrap handshake between WorkerLinter (main thread) and worker.ts.","triggerScenarios":"Constructing WorkerLinter with a binary option that is not a string URL (e.g. passing an ArrayBuffer, a URL object, undefined, or a WebAssembly.Module); calling worker.postMessage manually with a malformed [binaryUrl, dialect, glueFlavor] tuple.","commonSituations":"Config mistakes like new WorkerLinter({ binary: wasmBytes }) instead of a URL to the .wasm asset; bundler import returning a module default rather than a URL string; forgetting to pass binary so it is undefined in dev.","solutions":["Pass a string URL to the WASM binary, e.g. new WorkerLinter({ binary: wasmUrl }) or new WorkerLinter({ binary: new URL('./wasm.wasm', import.meta.url).toString() })","If you have bytes rather than a URL, convert/upload to a URL the worker can fetch (URL.createObjectURL(new Blob([bytes])))","Check WorkerLinter constructor docs for the expected binary option shape","Verify the value isn't undefined due to a failed dynamic import or env variable"],"exampleFix":"// before\nconst linter = new WorkerLinter({ binary: await import('./harper_wasm_bg.wasm') });\n// after\nconst linter = new WorkerLinter({ binary: new URL('./harper_wasm_bg.wasm', import.meta.url).toString() });","handlingStrategy":"type-guard","validationCode":"const binary = new URL('./harper_wasm_bg.wasm', import.meta.url).toString();\nif (typeof binary !== 'string') throw new Error('binary must be a string URL');","typeGuard":"function isBinaryUrl(v: unknown): v is string {\n  return typeof v === 'string' && (v.startsWith('/') || v.startsWith('http') || v.startsWith('blob:') || v.startsWith('data:'));\n}","tryCatchPattern":"try {\n  const linter = new WorkerLinter({ binary });\n  await linter.setup();\n} catch (e) {\n  if (e instanceof TypeError && e.message.includes('Expected binary to be a string of url')) {\n    console.error('WorkerLinter binary option must be a URL string, got:', typeof binary);\n  }\n  throw e;\n}","preventionTips":["Always pass a string URL (new URL(...).toString()) for the binary option","Don't pass imported WASM modules or ArrayBuffers directly to WorkerLinter","Check for undefined caused by failed dynamic imports or missing env vars"],"tags":["worker","wasm","type-error","configuration"],"backgroundTag":"invalid-argument-value","analyzedSha":"5fe7d5ab76492d83f3ecdbc3f1da83c75dcb6f83","analyzedAt":"2026-09-06T11:34:38.610Z","contentChangedAt":"2026-09-06T11:34:38.610Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}