{"record":{"id":"6707a461fad3c471","repo":"denoland/deno","slug":"startactivespan-requires-a-function-argument","errorCode":null,"errorMessage":"startActiveSpan requires a function argument","messagePattern":"startActiveSpan requires a function argument","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"ext/telemetry/telemetry.ts","lineNumber":396,"sourceCode":"    optionsOrFn: SpanOptions | F,\n    fnOrContext?: F | Context,\n    maybeFn?: F,\n  ) {\n    let options;\n    let context;\n    let fn;\n    if (typeof optionsOrFn === \"function\") {\n      options = undefined;\n      fn = optionsOrFn;\n    } else if (typeof fnOrContext === \"function\") {\n      options = optionsOrFn;\n      fn = fnOrContext;\n    } else if (typeof maybeFn === \"function\") {\n      options = optionsOrFn;\n      context = fnOrContext;\n      fn = maybeFn;\n    } else {\n      throw new Error(\"startActiveSpan requires a function argument\");\n    }\n    if (options?.root) {\n      context = ROOT_CONTEXT;\n    } else {\n      context = context ?? CURRENT.get() ?? ROOT_CONTEXT;\n    }\n    const span = this.startSpan(name, options, context);\n    const ctx = CURRENT.enter(context.setValue(SPAN_KEY, span));\n    try {\n      return ReflectApply(fn, undefined, [span]);\n    } finally {\n      setAsyncContext(ctx);\n    }\n  }\n\n  startSpan(name: string, options?: SpanOptions, context?: Context): Span {\n    if (options?.root) {\n      context = undefined;","sourceCodeStart":378,"sourceCodeEnd":414,"githubUrl":"https://github.com/denoland/deno/blob/a961cdec3b1948844414ebeecc697dcad76df2d1/ext/telemetry/telemetry.ts#L378-L414","documentation":"Thrown by Tracer.startActiveSpan() in Deno's built-in OpenTelemetry shim (ext/telemetry/telemetry.ts:374). The method resolves its argument overloads (name, fn), (name, options, fn), or (name, options, context, fn); if none of the second, third, or fourth argument is a function, it throws this Error. This mirrors @opentelemetry/api semantics where the span is only active for the duration of the synchronous callback.","triggerScenarios":"tracer.startActiveSpan('fetch') with no callback; tracer.startActiveSpan('fetch', { attributes: {...} }) with options but the callback forgotten; the fn variable being conditionally undefined at the call site (e.g. fn loaded from config); swapping the context and fn arguments so no checked position holds a function.","commonSituations":"Porting manual span code written with startSpan to startActiveSpan and forgetting the callback; refactors that extract the inline closure into a variable that can be undefined; JS code without TypeScript overloads catching the mistake at compile time.","solutions":["Pass the callback as the second argument: tracer.startActiveSpan(name, (span) => { ... })","If you need options, put them before the callback: tracer.startActiveSpan(name, { attributes }, (span) => { ... })","If the callback comes from a variable, guard with typeof fn === 'function' before calling","If you do not want an active-context callback, use tracer.startSpan(name, options, context) and end the span yourself"],"exampleFix":"// before\ntracer.startActiveSpan(\"fetch\", { attributes: { url } });\n\n// after\ntracer.startActiveSpan(\"fetch\", { attributes: { url } }, (span) => {\n  try {\n    return doFetch(url);\n  } finally {\n    span.end();\n  }\n});","handlingStrategy":"type-guard","validationCode":"if (typeof fn !== \"function\") {\n  throw new TypeError(\"startActiveSpan requires a function argument\");\n}\ntracer.startActiveSpan(name, options, fn);","typeGuard":"function isSpanCallback(\n  v: unknown,\n): v is (span: unknown) => unknown {\n  return typeof v === \"function\";\n}","tryCatchPattern":"try {\n  tracer.startActiveSpan(name, options, fn);\n} catch (e) {\n  if (e instanceof Error && e.message.includes(\"requires a function argument\")) {\n    // fall back to a manual span\n    const span = tracer.startSpan(name, options);\n    span.end();\n  } else {\n    throw e;\n  }\n}","preventionTips":["Type the call site against @opentelemetry/api overloads so TypeScript rejects missing callbacks","Enable strict TypeScript (noImplicitAny, strictBindCallApply) so wrong-arity calls surface","Never pass optionally-defined callbacks; assert or default them first"],"tags":["opentelemetry","tracing","telemetry","callback","api-misuse"],"backgroundTag":"missing-callback-argument","analyzedSha":"a961cdec3b1948844414ebeecc697dcad76df2d1","analyzedAt":"2026-08-20T13:07:44.778Z","contentChangedAt":"2026-08-20T13:07:44.778Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}