BabylonJS/Babylon.js · error
Property "${propertyKey.toString()}" of object "${target}" i
Error message
Property "${propertyKey.toString()}" of object "${target}" is not a function. What it means
InterceptFunction replaces a property on a target object with an intercepting proxy function, so it requires the property to already be a function. Before instrumenting, it reads the property via Reflect.get and throws this error if the resolved value is not callable. This guards against instrumenting data properties, undefined keys, or typos in the property name.
Source
Thrown at packages/dev/inspector-v2/src/instrumentation/functionInstrumentation.ts:39
* @returns A disposable that removes the hooks when disposed and returns the object to its original state.
*/
// This overload only matches when K is a specific literal key (not a union like keyof T)
export function InterceptFunction<T extends object, K extends keyof T>(
target: T,
propertyKey: string extends K ? never : number extends K ? never : symbol extends K ? never : K,
hooks: NonNullable<T[K]> extends (...args: infer Args) => unknown ? FunctionHooks<Args> : FunctionHooks
): 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()));
View on GitHub (pinned to 0592b347b8)
Solutions
- Verify the exact property name exists on the target at interception time (log Object.keys(target) / console.log(target)).
- Fix typos and confirm the property is a function (typeof target[key] === 'function') before calling InterceptFunction.
- If the property is assigned asynchronously, defer interception until after assignment (e.g. await initialization, or intercept on the prototype where the method is defined).
- If the value is data, use a property/value interception mechanism instead of function instrumentation.
Example fix
// before
InterceptFunction(player, 'paly' /* typo */, hooks);
// after
if (typeof player.play === 'function') {
InterceptFunction(player, 'play', hooks);
} Defensive patterns
Strategy: validation
Validate before calling
function canInterceptFunction(target, propertyKey) {
const value = Reflect.get(target, propertyKey, target);
return typeof value === 'function';
}
if (!canInterceptFunction(target, 'play')) throw new TypeError('target.play is not a function'); Type guard
function isInterceptableFunction(target: object, key: PropertyKey): boolean {
return typeof (target as any)[key] === 'function';
} Try / catch
try {
InterceptFunction(target, propertyKey, hooks);
} catch (e) {
if (String((e as Error)?.message).includes('is not a function')) {
console.warn(`Cannot intercept ${String(propertyKey)}: not a function on`, target);
return null; // skip instrumentation gracefully
}
throw e;
} Prevention
- Always confirm typeof target[key] === 'function' before InterceptFunction.
- Check for typos against the object's actual API surface (console.dir / Object.keys).
- Defer interception until asynchronous initialization has assigned the method.
- Use TypeScript types for the target so nonexistent members are caught at compile time.
When it happens
Trigger: Calling InterceptFunction(target, propertyKey, hooks) (directly or via useInterceptObservable/hookMainSoundTrack/playHook/stopHook/animateHook/setSelectedItem) when target[propertyKey] is undefined, a data value, a getter returning a non-function, or the property name is misspelled.
Common situations: Typo in the method name; instrumenting an object whose API changed between library versions so the method no longer exists; trying to intercept a plain data field or a property that is only assigned later (asynchronously) before it is set; targeting a module namespace object or a frozen/bound copy where the method lives on the prototype under a different key.
Related errors
- Property "${propertyKey.toString()}" of object "${target}" i
- Failed to define new function "${propertyKey.toString()}" on
- Failed to restore original function "${propertyKey.toString(
- Atmosphere only supports one light source currently.
- Multi-file loading not allowed on env files.
AI-assisted analysis of BabylonJS/Babylon.js@0592b347b8 (2026-08-30).
Data as JSON: /api/errors/c8e80ebac83b1098.
Report an issue: GitHub.