BabylonJS/Babylon.js · error
Failed to define new function "${propertyKey.toString()}" on
Error message
Failed to define new function "${propertyKey.toString()}" on object "${target}". What it means
After validating the property, InterceptFunction installs the interceptor by redefining the property with Reflect.defineProperty; the property is only considered intercepted if that call returns true. If the redefinition fails, this error is thrown. This usually means the descriptor check passed but the engine still refused the redefine (e.g. Proxy invariants, exotic objects, or a change between the descriptor check and the define).
Source
Thrown at packages/dev/inspector-v2/src/instrumentation/functionInstrumentation.ts:74
if (!hooksMap) {
InterceptorHooksMaps.set(target, (hooksMap = new Map()));
}
// Get or create the hooks array for the property key.
let hooksForKey = hooksMap.get(propertyKey);
if (!hooksForKey) {
hooksMap.set(propertyKey, (hooksForKey = []));
if (
// Replace the function with a new one that calls the hooks in addition to the original function.
!Reflect.set(target, propertyKey, function (this: unknown, ...args: unknown[]) {
const result = Reflect.apply(originalFunction, this, args);
for (const { afterCall } of hooksForKey!) {
afterCall?.(...args);
}
return result;
})
) {
throw new Error(`Failed to define new function "${propertyKey.toString()}" on object "${target}".`);
}
}
hooksForKey.push(hooks as FunctionHooks<unknown[]>);
let isDisposed = false;
return {
dispose: () => {
if (!isDisposed) {
// Remove the hooks from the hooks array for the property key.
hooksForKey.splice(hooksForKey.indexOf(hooks), 1);
// If there are no more hooks for the property key, remove the property from the hooks map.
if (hooksForKey.length === 0) {
hooksMap.delete(propertyKey);
// If there are no more hooks for the target object, remove the hooks map from the WeakMap.
if (hooksMap.size === 0) {
InterceptorHooksMaps.delete(target);
View on GitHub (pinned to 0592b347b8)
Solutions
- Intercept the underlying raw object, not a Proxy wrapper around it.
- Re-check that the property is still configurable/writable immediately before intercepting; avoid racing other code that redefines it.
- For builtin/host objects, wrap them in your own plain object with delegating methods and intercept that.
- Catch this error and fall back to manual instrumentation (call hooks.afterCall explicitly at the call site).
Example fix
// before InterceptFunction(proxyWrappedPlayer, 'play', hooks); // defineProperty fails on proxy invariants // after InterceptFunction(rawPlayer, 'play', hooks); // intercept the raw target, not the proxy
Defensive patterns
Strategy: try-catch
Validate before calling
function isPlainInterceptableTarget(target: object, key: PropertyKey): boolean {
const d = Object.getOwnPropertyDescriptor(target, key);
return (!d || (d.configurable && d.writable !== false)) && !Symbol.toStringTag; // also avoid proxies/exotic targets
}
// check before intercepting:
if (!isPlainInterceptableTarget(target, 'play')) throw new TypeError('target not safely redefinable'); Type guard
function isRawInterceptable(target: object, key: PropertyKey): boolean {
if (typeof Proxy !== 'undefined') {
try { Object.getOwnPropertyDescriptor(target, key); } catch { return false; } // proxies may throw on invariants
}
const d = Object.getOwnPropertyDescriptor(target, key);
return !d || (d.configurable && d.writable !== false);
} Try / catch
try {
const handle = InterceptFunction(target, propertyKey, hooks);
return handle;
} catch (e) {
if (String((e as Error)?.message).includes('Failed to define new function')) {
console.warn(`Redefinition failed for ${String(propertyKey)}; falling back to manual hooks`);
return null; // call hooks.afterCall manually at the call site
}
throw e;
} Prevention
- Intercept raw objects, not Proxy wrappers or exotic host/builtin objects.
- Minimize the window between descriptor validation and interception to avoid races.
- Do not intercept module namespace objects or objects with internal slots.
- Test interception in a try/catch during setup so instrumentation failures degrade gracefully.
When it happens
Trigger: Reflect.defineProperty(target, propertyKey, replacementDescriptor) returning false during InterceptFunction — e.g. the target is a Proxy whose invariant constraints reject the redefinition, the property changed between getOwnPropertyDescriptor and defineProperty, or the target is an exotic/builtin object that disallows redefining the property.
Common situations: Instrumenting objects behind a Proxy (invariant violations); hooking host/builtin objects (DOM, Node internals) with unusual internal slots; concurrent code redefining the same property mid-interception; intercepting properties on module namespace objects.
Related errors
- Property "${propertyKey.toString()}" of object "${target}" i
- Property "${propertyKey.toString()}" of object "${target}" i
- Failed to restore original function "${propertyKey.toString(
- Unknown interceptor type: ${type}
- At least one hook must be provided.
AI-assisted analysis of BabylonJS/Babylon.js@0592b347b8 (2026-08-30).
Data as JSON: /api/errors/76d3d037753b637a.
Report an issue: GitHub.