{"record":{"id":"e4d5e51741137146","repo":"RocketChat/Rocket.Chat","slug":"invalid-api-parameter-provided-it-must-be-a-valid","errorCode":null,"errorMessage":"Invalid Api parameter provided, it must be a valid IApi object.","messagePattern":"Invalid Api parameter provided, it must be a valid IApi object\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"apps/meteor/app/apps/server/bridges/api.ts","lineNumber":92,"sourceCode":"\t\t\trouter[method](\n\t\t\t\troutePath,\n\t\t\t\tauthenticationMiddleware({ rejectUnauthorized: !!endpoint.authRequired }),\n\t\t\t\tMeteor.bindEnvironment(this._appApiExecutor(endpoint, appId)),\n\t\t\t);\n\t\t}\n\t}\n\n\tpublic async unregisterApis(appId: string): Promise<void> {\n\t\tthis.orch.debugLog(`The App ${appId} is unregistering all apis`);\n\n\t\tif (this.appRouters.get(appId)) {\n\t\t\tthis.appRouters.delete(appId);\n\t\t}\n\t}\n\n\tprivate _verifyApi(api: IApi, endpoint: IApiEndpoint): void {\n\t\tif (typeof api !== 'object') {\n\t\t\tthrow new Error('Invalid Api parameter provided, it must be a valid IApi object.');\n\t\t}\n\n\t\tif (typeof endpoint.path !== 'string') {\n\t\t\tthrow new Error('Invalid Api parameter provided, it must be a valid IApi object.');\n\t\t}\n\t}\n\n\tprivate _appApiExecutor(endpoint: IApiEndpoint, appId: string): RequestHandler {\n\t\treturn (req: IRequestWithPrivateHash, res: Response): void => {\n\t\t\tconst request: IApiRequest = {\n\t\t\t\tmethod: req.method.toLowerCase() as RequestMethod,\n\t\t\t\theaders: req.headers as { [key: string]: string },\n\t\t\t\tquery: (req.query as { [key: string]: string }) || {},\n\t\t\t\tparams: req.params || {},\n\t\t\t\tcontent: req.body,\n\t\t\t\tprivateHash: req._privateHash,\n\t\t\t\tuser: req.user && this.orch.getConverters()?.get('users')?.convertToApp(req.user),\n\t\t\t};","sourceCodeStart":74,"sourceCodeEnd":110,"githubUrl":"https://github.com/RocketChat/Rocket.Chat/blob/f9d3ec372bb580fa8d036f94cf03925a478ef768/apps/meteor/app/apps/server/bridges/api.ts#L74-L110","documentation":"Thrown by the private `_verifyApi` guard inside `AppApisBridge.registerApi` (api.ts:90-93). registerApi runs once per endpoint when an App registers an API, and `_verifyApi(api, endpoint)` is its first action. This first check asserts the `IApi` object (visibility, security, endpoints) is typeof 'object'. Reaching it means the AppApi wrapper was constructed with a non-object `api` value (undefined, null, string, number) — i.e. the App's API declaration produced a malformed IApi that slipped past the apps-engine runtime's own construction.","triggerScenarios":"An App calls `provideApi(...)` (or its App class returns an API declaration) where the `api` field is not an object: `api: undefined`, a string, or a number. The apps-engine builds an AppApi from that and calls registerApi, which immediately runs `_verifyApi` and fails this check.","commonSituations":"App upgraded across apps-engine versions where the IApi shape changed; a destructured/spread export that accidentally dropped the `api` root; a TypeScript `as IApi` cast hiding a missing value; a partial object built at runtime whose api lookup returned undefined.","solutions":["Inspect the object passed to provideApi: confirm `api` is an object containing `visibility`, `security`, and an `endpoints` array.","Remove any `as IApi` casts so TypeScript flags the missing shape at compile time.","Align the App's apps-engine dependency version with the server's expected IApi interface."],"exampleFix":"// before\nprovideApi({ api: undefined, endpoints: [...] })\n// after\nprovideApi({\n  api: { visibility: ApiVisibility.PUBLIC, security: ApiSecurity.UNSECURE, endpoints: [...] },\n})","handlingStrategy":"type-guard","validationCode":"if (!isIApi(myApi)) {\n  throw new Error('Refusing to register API: api is not a valid IApi object');\n}\nprovideApi({ api: myApi, /* endpoints... */ });","typeGuard":"function isIApi(api: unknown): api is IApi {\n  return typeof api === 'object' && api !== null\n    && typeof (api as any).visibility === 'number'\n    && typeof (api as any).security === 'number'\n    && Array.isArray((api as any).endpoints);\n}","tryCatchPattern":null,"preventionTips":["Never cast to IApi with `as` when the source is dynamic; use a type guard.","Unit-test the App's API declaration shape before packaging the app.","Keep the App's apps-engine dependency version aligned with the target server."],"tags":["apps-engine","validation","api","typescript"],"backgroundTag":null,"analyzedSha":"f9d3ec372bb580fa8d036f94cf03925a478ef768","analyzedAt":"2026-08-12T19:07:17.372Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}