{"record":{"id":"61916c29e34bedcd","repo":"GopeedLab/gopeed","slug":"execute-expects-a-string-or-function-got-t-q-61916c","errorCode":null,"errorMessage":"execute expects a string or function, got %T (%q)","messagePattern":"execute expects a string or function, got %T \\(%q\\)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/download/extension_runtime_webview.go","lineNumber":146,"sourceCode":"\t\treturn goja.Undefined()\n\t})\n\t_ = obj.Set(\"goto\", func(call goja.FunctionCall) goja.Value {\n\t\turl, err := requireStringArg(call, 0, \"url\")\n\t\tif err != nil {\n\t\t\tpanic(vm.ToValue(err))\n\t\t}\n\t\tif err := page.Goto(\n\t\t\turl,\n\t\t\toptionalMap(call.Argument(1)),\n\t\t); err != nil {\n\t\t\tpanic(vm.ToValue(err))\n\t\t}\n\t\treturn goja.Undefined()\n\t})\n\t_ = obj.Set(\"execute\", func(call goja.FunctionCall) goja.Value {\n\t\texpression, err := enginewebview.NormalizeExecutableValue(call.Argument(0))\n\t\tif err != nil {\n\t\t\tpanic(vm.ToValue(err))\n\t\t}\n\t\tresult, err := page.Execute(expression, exportArgs(call.Arguments[1:])...)\n\t\tif err != nil {\n\t\t\tpanic(vm.ToValue(err))\n\t\t}\n\t\treturn vm.ToValue(result)\n\t})\n\t_ = obj.Set(\"focus\", func(call goja.FunctionCall) goja.Value {\n\t\tselector, err := requireStringArg(call, 0, \"selector\")\n\t\tif err != nil {\n\t\t\tpanic(vm.ToValue(err))\n\t\t}\n\t\tif err := page.Focus(selector); err != nil {\n\t\t\tpanic(vm.ToValue(err))\n\t\t}\n\t\treturn goja.Undefined()\n\t})\n\t_ = obj.Set(\"click\", func(call goja.FunctionCall) goja.Value {","sourceCodeStart":128,"sourceCodeEnd":164,"githubUrl":"https://github.com/GopeedLab/gopeed/blob/7b7327ffb30816273a74b142cccc0bc10c5a4c67/pkg/download/extension_runtime_webview.go#L128-L164","documentation":"The typed variant of the execute argument error, produced by the fallback branch of NormalizeExecutableValue (pkg/download/engine/webview/runtime.go:590-594). The value was present but could not be interpreted: it is not a string, not a callable function (detected via goja.AssertFunction and serialized with toString), and its string form does not look like function source. The message includes the Go type (%T) and the coerced value (%q) to identify exactly what was passed.","triggerScenarios":"Passing numbers (page.execute(42)), booleans, plain objects or arrays as the first argument; passing undefined or null explicitly (they export to non-callable, non-string values); passing a Proxy or class instance that is not itself callable; passing a string like \"42\" is fine, but \"4 2\" style non-source strings are not.","commonSituations":"Forwarding a parsed JSON value (object) instead of the desired expression string; passing a DOM element wrapper or handle returned by another API; passing a function-like string that got truncated; undefined leaking from optional chaining.","solutions":["Pass a string containing a JS expression: page.execute(\"document.querySelector('#dl').href\")","Or pass an actual function: page.execute(() => document.title)","If the value is dynamic, stringify first and verify it is non-empty: page.execute(String(expr))"],"exampleFix":"// before\nconst expr = config.expr; // number 42 from settings\npage.execute(expr);\n\n// after\nif (typeof config.expr !== \"string\" && typeof config.expr !== \"function\") {\n  throw new TypeError(\"expr must be a string or function\");\n}\npage.execute(config.expr);","handlingStrategy":"type-guard","validationCode":"if (typeof expr !== \"string\" && typeof expr !== \"function\") {\n  throw new TypeError(`execute expects string or function, got ${typeof expr}`);\n}","typeGuard":"function isExecutable(v) {\n  return typeof v === \"string\" || typeof v === \"function\";\n}","tryCatchPattern":"try {\n  page.execute(expr);\n} catch (e) {\n  if (String(e.message ?? e).includes(\"execute expects\")) {\n    gopeed.logger.warn(`invalid execute argument: ${typeof expr}`);\n  } else {\n    throw e;\n  }\n}","preventionTips":["Forward function references, never call results or parsed JSON objects","Keep expression strings intact; avoid templating that can truncate them","Validate settings-provided expressions at extension startup"],"tags":["extension","webview","execute","type-validation"],"backgroundTag":null,"analyzedSha":"7b7327ffb30816273a74b142cccc0bc10c5a4c67","analyzedAt":"2026-08-16T02:51:03.250Z","schemaVersion":2},"datasetVersion":"2026-08-16T03:17:38.424Z"}