{"record":{"id":"8ebe6677ae7c9b19","repo":"pulumi/pulumi","slug":"function-is-not-a-bound-function","errorCode":null,"errorMessage":"function is not a bound function","messagePattern":"function is not a bound function","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"sdk/nodejs/runtime/closure/v8.ts","lineNumber":336,"sourceCode":"    }\n\n    // Extract value and clear our table entry.\n    const val = context.calls[tableId];\n    delete context.calls[tableId];\n\n    return val;\n}\n\nexport async function getBoundFunction(\n    func: Function,\n): Promise<{ targetFunctionText: string; boundThisValue: any; boundArgsValues: any[] }> {\n    const functionId = await getRuntimeIdForFunctionAsync(func);\n    const { internalProperties } = await runtimeGetPropertiesAsync(functionId, /*ownProperties:*/ false);\n\n    const desc = internalProperties.find((p) => p.name === \"[[TargetFunction]]\");\n    const targetFunctionText = desc?.value?.description;\n    if (!targetFunctionText) {\n        throw new Error(\"function is not a bound function\");\n    }\n\n    const boundThisValue = internalProperties.find((p) => p.name === \"[[BoundThis]]\")?.value?.value;\n\n    const boundArgsObjectId = internalProperties.find((p) => p.name === \"[[BoundArgs]]\")?.value?.objectId;\n    let boundArgsValues: any[] = [];\n    if (boundArgsObjectId) {\n        const { properties } = await runtimeGetPropertiesAsync(boundArgsObjectId, /*ownProperties:*/ false);\n        boundArgsValues = properties.filter((p) => p.enumerable).map((p) => p.value?.value);\n    }\n\n    return { targetFunctionText, boundThisValue, boundArgsValues };\n}\n","sourceCodeStart":318,"sourceCodeEnd":350,"githubUrl":"https://github.com/pulumi/pulumi/blob/793f7b2e160db4321fb7fb6b0607461e01cb251e/sdk/nodejs/runtime/closure/v8.ts#L318-L350","documentation":"During closure serialization the SDK inspects a captured function to determine its runtime/remote execution metadata. When the V8 inspector reports the function has no [[TargetFunction]] internal property, it is not a bound function (created via Function.prototype.bind), so the SDK cannot unwrap the original target and throws. This code path expects `func` to be a bound function whose target can be resolved.","triggerScenarios":"Calling serializeFunction/captureOutputAsync (directly or via exports in a Pulumi program) with a function whose runtime descriptor is retrieved via getRuntimeIdForFunctionAsync but which is not created with `.bind()` — e.g. passing a plain arrow function or regular function where the serializer expected `fn.bind(null, ...)` with captured args.","commonSituations":"Custom closure serialization in provider/plugin code; upgrading the Node runtime or enabling V8 flags that change internal property reporting; hand-written code that mimics the SDK's bound-function capture pattern but passes an unbound function.","solutions":["Bind the function before serializing: pass `func.bind(null, ...capturedValues)` instead of the raw function.","Verify the value passed to the serializer is actually a function, not a wrapper object or proxy.","Check that the Node/V8 version in use still reports [[TargetFunction]] via the inspector protocol; align with a supported runtime version."],"exampleFix":"// before\nserializeFunction(myHandler);\n// after\nserializeFunction(myHandler.bind(null, configValue));","handlingStrategy":"type-guard","validationCode":"// before serializing\nif (typeof func !== \"function\") throw new TypeError(\"expected a function\");","typeGuard":"function isBoundFunction(f: unknown): f is Function {\n  return typeof f === \"function\" && f.name.startsWith(\"bound \");\n}","tryCatchPattern":"try {\n  await serializeFunction(fn);\n} catch (err) {\n  if ((err as Error).message === \"function is not a bound function\") {\n    fn = fn.bind(null, ...captured);\n    await serializeFunction(fn);\n  } else throw err;\n}","preventionTips":["Always use fn.bind(null, ...) to capture values for closure serialization","Assert typeof operand === 'function' before calling the serializer","Keep the Node runtime on a version supported by the Pulumi SDK"],"tags":["closure","serialization","nodejs","v8"],"backgroundTag":"function-not-bound","analyzedSha":"793f7b2e160db4321fb7fb6b0607461e01cb251e","analyzedAt":"2026-08-31T09:36:43.099Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}