RocketChat/Rocket.Chat · error · Error

Invalid Api parameter provided, it must be a valid IApi obje

Error message

Invalid Api parameter provided, it must be a valid IApi object.

What it means

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.

Source

Thrown at apps/meteor/app/apps/server/bridges/api.ts:92

			router[method](
				routePath,
				authenticationMiddleware({ rejectUnauthorized: !!endpoint.authRequired }),
				Meteor.bindEnvironment(this._appApiExecutor(endpoint, appId)),
			);
		}
	}

	public async unregisterApis(appId: string): Promise<void> {
		this.orch.debugLog(`The App ${appId} is unregistering all apis`);

		if (this.appRouters.get(appId)) {
			this.appRouters.delete(appId);
		}
	}

	private _verifyApi(api: IApi, endpoint: IApiEndpoint): void {
		if (typeof api !== 'object') {
			throw new Error('Invalid Api parameter provided, it must be a valid IApi object.');
		}

		if (typeof endpoint.path !== 'string') {
			throw new Error('Invalid Api parameter provided, it must be a valid IApi object.');
		}
	}

	private _appApiExecutor(endpoint: IApiEndpoint, appId: string): RequestHandler {
		return (req: IRequestWithPrivateHash, res: Response): void => {
			const request: IApiRequest = {
				method: req.method.toLowerCase() as RequestMethod,
				headers: req.headers as { [key: string]: string },
				query: (req.query as { [key: string]: string }) || {},
				params: req.params || {},
				content: req.body,
				privateHash: req._privateHash,
				user: req.user && this.orch.getConverters()?.get('users')?.convertToApp(req.user),
			};

View on GitHub (pinned to f9d3ec372b)

Solutions

  1. Inspect the object passed to provideApi: confirm `api` is an object containing `visibility`, `security`, and an `endpoints` array.
  2. Remove any `as IApi` casts so TypeScript flags the missing shape at compile time.
  3. Align the App's apps-engine dependency version with the server's expected IApi interface.

Example fix

// before
provideApi({ api: undefined, endpoints: [...] })
// after
provideApi({
  api: { visibility: ApiVisibility.PUBLIC, security: ApiSecurity.UNSECURE, endpoints: [...] },
})
Defensive patterns

Strategy: type-guard

Validate before calling

if (!isIApi(myApi)) {
  throw new Error('Refusing to register API: api is not a valid IApi object');
}
provideApi({ api: myApi, /* endpoints... */ });

Type guard

function isIApi(api: unknown): api is IApi {
  return typeof api === 'object' && api !== null
    && typeof (api as any).visibility === 'number'
    && typeof (api as any).security === 'number'
    && Array.isArray((api as any).endpoints);
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of RocketChat/Rocket.Chat@f9d3ec372b (2026-08-12). Data as JSON: /api/errors/e4d5e51741137146. Report an issue: GitHub.