BabylonJS/Babylon.js · error
Property "${propertyKey.toString()}" of object "${target}" i
Error message
Property "${propertyKey.toString()}" of object "${target}" is not configurable. What it means
Function instrumentation works by redefining the property on the target with Reflect.defineProperty, which is only possible for configurable properties. If Reflect.getOwnPropertyDescriptor returns a descriptor whose configurable flag is false, the property is immutable and the library refuses to intercept it with this error. This prevents silently failing to swap the function.
Source
Thrown at packages/dev/inspector-v2/src/instrumentation/functionInstrumentation.ts:46
): IDisposable;
// Fallback overload for generic/dynamic cases where the function type cannot be inferred
export function InterceptFunction<T extends object>(target: T, propertyKey: keyof T, hooks: FunctionHooks): IDisposable;
/** @internal */
export function InterceptFunction<T extends object>(target: T, propertyKey: keyof T, hooks: FunctionHooks): IDisposable {
if (!hooks.afterCall) {
throw new Error("At least one hook must be provided.");
}
const originalFunction = Reflect.get(target, propertyKey, target) as (...args: any) => any;
if (typeof originalFunction !== "function") {
throw new Error(`Property "${propertyKey.toString()}" of object "${target}" is not a function.`);
}
// Make sure the property is configurable and writable, otherwise it is immutable and cannot be intercepted.
const propertyDescriptor = Reflect.getOwnPropertyDescriptor(target, propertyKey);
if (propertyDescriptor) {
if (!propertyDescriptor.configurable) {
throw new Error(`Property "${propertyKey.toString()}" of object "${target}" is not configurable.`);
}
if (propertyDescriptor.writable === false || (propertyDescriptor.writable === undefined && !propertyDescriptor.set)) {
throw new Error(`Property "${propertyKey.toString()}" of object "${target}" is readonly.`);
}
}
// Get or create the hooks map for the target object.
let hooksMap = InterceptorHooksMaps.get(target);
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 (
View on GitHub (pinned to 0592b347b8)
Solutions
- Intercept a configurable wrapper: create your own object whose method delegates to the original and intercept that instead.
- Unfreeze/clone the object: const copy = {...target} (restores configurability for own props) and intercept the copy, then route callers through it.
- If you own the definition, change Object.defineProperty options to configurable: true (and writable: true).
- For prototype methods, intercept on the prototype only if that descriptor is configurable; otherwise wrap at the call site.
Example fix
// before
Object.defineProperty(obj, 'play', { value: fn, configurable: false });
InterceptFunction(obj, 'play', hooks);
// after
Object.defineProperty(obj, 'play', { value: fn, configurable: true, writable: true });
InterceptFunction(obj, 'play', hooks); Defensive patterns
Strategy: validation
Validate before calling
function isConfigurable(target, propertyKey) {
const d = Reflect.getOwnPropertyDescriptor(target, propertyKey);
return !d || d.configurable;
}
if (!isConfigurable(target, 'play')) throw new TypeError('target.play is not configurable'); Type guard
function hasConfigurableDescriptor(target: object, key: PropertyKey): boolean {
const d = Object.getOwnPropertyDescriptor(target, key);
return d === undefined || d.configurable === true;
} Try / catch
try {
InterceptFunction(target, propertyKey, hooks);
} catch (e) {
if (String((e as Error)?.message).includes('is not configurable')) {
console.warn(`Skipping interception of ${String(propertyKey)}: non-configurable property`);
return null;
}
throw e;
} Prevention
- Check Object.getOwnPropertyDescriptor(target, key)?.configurable before intercepting.
- Do not call Object.freeze/Object.seal on objects you plan to instrument.
- Avoid intercepting module namespace objects and engine built-ins with non-configurable methods.
- Intercept a wrapper object you own instead of hardened third-party objects.
When it happens
Trigger: Calling InterceptFunction on a property that was defined with configurable: false — e.g. built-ins like Function.prototype.call, methods defined via Object.defineProperty with configurable:false, frozen (Object.freeze) or sealed (Object.seal) objects, or class fields made non-configurable.
Common situations: Trying to hook native/built-in methods that are non-configurable in some engines; intercepting methods on objects passed through Object.freeze for immutability; instrumenting module exports or namespace objects; attempts to hook secure/hardened objects.
Related errors
- Property "${propertyKey.toString()}" of object "${target}" i
- Failed to restore original function "${propertyKey.toString(
- Failed to define new property "${propertyKey.toString()}" on
- Property "${propertyKey.toString()}" of object "${target}" i
- Failed to define new function "${propertyKey.toString()}" on
AI-assisted analysis of BabylonJS/Babylon.js@0592b347b8 (2026-08-30).
Data as JSON: /api/errors/a23454ee0fda2291.
Report an issue: GitHub.