hcengineering/platform · error
Method '${methodName}' not found in service implementation
Error message
Method '${methodName}' not found in service implementation What it means
handleProxyCall receives a remote method invocation (proxy requests) and looks the method name up on the registered service implementation before invoking it with the given params. If the property is missing or not a function, the library throws, since there is no code to execute for that RPC. This surfaces a client/server contract mismatch.
Source
Thrown at foundations/net/packages/core/src/proxy.ts:111
* ```
*/
export async function handleProxyCall<T extends ServiceImplementation> (
implementation: T,
method: string,
params: any[],
interfaceName?: string
): Promise<any> {
// Strip interface name prefix if present
let methodName = method
if (interfaceName !== undefined && method.startsWith(`${interfaceName}.`)) {
methodName = method.substring(interfaceName.length + 1)
}
// Get the method from the implementation
const fn = implementation[methodName]
if (fn === undefined || typeof fn !== 'function') {
throw new Error(`Method '${methodName}' not found in service implementation`)
}
// Call the method with the provided parameters
const result = await fn.apply(implementation, params)
return result
}
/**
* Creates a request handler wrapper for a service implementation.
* This is a convenience function that wraps handleProxyCall.
*
* @template T - The service interface type
* @param implementation - The actual implementation of the service interface
* @param interfaceName - Optional interface name prefix to strip from method names
* @returns A request handler function
*
* @example
* ```typescriptView on GitHub (pinned to 63e28dc964)
Solutions
- Compare the method invoked by the client with the actual methods on the server implementation; fix the name mismatch.
- Deploy matching versions of client and server so the service interface is identical on both sides.
- Verify the correct implementation object was registered for the service (not an empty or wrong object).
- Add a shared interface/type for the service and typecheck both sides to catch drift at build time.
Example fix
// before (server)
registerService('calc', { add: (a, b) => a + b })
// client calls proxy.subtract(3, 1) -> throws
// after
registerService('calc', {
add: (a, b) => a + b,
subtract: (a, b) => a - b
}) // or update client to only call add Defensive patterns
Strategy: type-guard
Validate before calling
// Client-side check before invoking the proxy:
if (typeof (serviceImplementation as any)?.[methodName] !== 'function') {
throw new Error(`service does not implement ${methodName}`)
} Type guard
function hasMethod<T extends object>(impl: T, m: string): impl is T & Record<typeof m, (...args: any[]) => any> {
return typeof (impl as any)[m] === 'function'
}
if (!hasMethod(implementation, methodName)) throw new Error(`missing method ${methodName}`) Try / catch
try {
return await proxy[methodName](...args)
} catch (e) {
if (typeof (e as Error).message === 'string' && e.message.includes('not found in service implementation')) {
console.error(`RPC contract mismatch: ${methodName} missing on server`, e)
// surface a typed RemoteMethodNotFound error to the caller
}
throw e
} Prevention
- Define the service interface in a shared package consumed by both client and server, and typecheck both.
- Keep client and server deployments version-locked; reject incompatible versions at handshake.
- Never rely on stringly-typed method names — derive them from the shared interface keys.
- Add an integration test that calls every interface method through the proxy.
When it happens
Trigger: A client proxy invokes methodName that does not exist on the server-side implementation object — method renamed or removed on the server, client generated against an older service interface, or a typo in the method name.
Common situations: Version skew: client updated to a new interface while server still runs the old implementation; calling an internal/private helper that isn't part of the service; passing the wrong implementation object when registering the service; TypeScript types out of sync across packages.
Related errors
- platform.status.ConnectionClosed
- HTTP error ${res.status}
- result.error
- Map is not allowed in model
- Set is not allowed in model
AI-assisted analysis of hcengineering/platform@63e28dc964 (2026-08-29).
Data as JSON: /api/errors/80d7dac4dfa02bac.
Report an issue: GitHub.