{"record":{"id":"77d30777a2086d56","repo":"HeyPuter/puter","slug":"bad-request-77d307","errorCode":"bad_request","errorMessage":"Missing or invalid `interface`","messagePattern":"Missing or invalid `interface`","errorType":"http","errorClass":"HttpError","httpStatus":400,"severity":"error","filePath":"src/backend/controllers/drivers/DriverController.ts","lineNumber":239,"sourceCode":"                    key: 'user',\n                },\n            },\n            this.#handleListInterfaces,\n        );\n    }\n\n    // -- Handlers ----------------------------------------------------\n\n    #handleCall = async (req: Request, res: Response): Promise<void> => {\n        const {\n            interface: ifaceName,\n            method,\n            driver: driverName,\n            args = {},\n        } = (req.body ?? {}) as Record<string, unknown>;\n\n        if (!ifaceName || typeof ifaceName !== 'string') {\n            throw new HttpError(400, 'Missing or invalid `interface`', {\n                legacyCode: 'bad_request',\n            });\n        }\n        if (!method || typeof method !== 'string') {\n            throw new HttpError(400, 'Missing or invalid `method`', {\n                legacyCode: 'bad_request',\n            });\n        }\n        const requestedDriver =\n            typeof driverName === 'string' ? driverName : undefined;\n\n        const driver = this.resolve(ifaceName, requestedDriver);\n        if (!driver) {\n            const resolvedName = requestedDriver ?? this.getDefault(ifaceName);\n            throw new HttpError(\n                404,\n                `Driver not found: ${ifaceName}:${resolvedName ?? '(no default)'}`,\n                { legacyCode: 'not_found' },","sourceCodeStart":221,"sourceCodeEnd":257,"githubUrl":"https://github.com/HeyPuter/puter/blob/908ec23eda38526170322c3edf71ba45ecb1ca95/src/backend/controllers/drivers/DriverController.ts#L221-L257","documentation":"Thrown by POST /drivers/call when body.interface is missing, empty, or not a string. The interface name (e.g. 'puter-chat-completion') selects which driver registry to dispatch into; without a valid one the resolver cannot start.","triggerScenarios":"POST /drivers/call with no interface field, interface: 42, interface: { name:'...' }, or interface: '' (empty string is falsy and rejected by the `!ifaceName` short-circuit).","commonSituations":"Client building the RPC payload from an untyped object and forgetting the interface key; an SDK wrapper that names it `service` or `driver` instead of `interface`; JSON body parsed as query params so body is empty.","solutions":["Send interface as a non-empty string naming a registered interface, e.g. {\"interface\":\"puter-chat-completion\", \"method\":\"complete\", \"args\":{...}}.","Confirm the body is JSON (Content-Type: application/json) — a form-encoded or empty body yields undefined interface.","If extending the SDK, centralize the interface token in a constant so it is never omitted."],"exampleFix":"// before\n{ method: 'complete', args: { prompt } }\n// after\n{ interface: 'puter-chat-completion', method: 'complete', args: { prompt } }","handlingStrategy":"type-guard","validationCode":"if (typeof ifaceName !== 'string' || ifaceName.length === 0) {\n  throw new Error('interface required');\n}","typeGuard":"const isInterfaceName = (v: unknown): v is string =>\n  typeof v === 'string' && v.length > 0;","tryCatchPattern":null,"preventionTips":["Send the body as JSON with Content-Type: application/json.","Use the documented interface token exactly.","Centralize the interface constant in SDK wrappers."],"tags":["validation","drivers","bad-request","rpc"],"backgroundTag":null,"analyzedSha":"908ec23eda38526170322c3edf71ba45ecb1ca95","analyzedAt":"2026-08-12T20:53:15.911Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}