RocketChat/Rocket.Chat · error · Meteor.Error
error-invalid-redirectUri
error-invalid-redirectUri
Error message
Invalid redirectUri
What it means
First redirectUri gate inside addOAuthApp: the value must exist, be a string, and not be whitespace-only. As with the name check, the REST ajv schema already requires a string, so whitespace-only bodies are the realistic trigger; entirely missing or non-string values only occur on direct/internal calls that bypass the route schema.
Source
Thrown at apps/meteor/server/lib/auth/oauth2-server/addOAuthApp.ts:35
if (!user?.username) {
// TODO: username is required, but not always present
throw new Meteor.Error('error-invalid-user', 'Invalid user', { method: 'addOAuthApp' });
}
if (!(await hasPermissionAsync(uid, 'manage-oauth-apps'))) {
throw new Meteor.Error('error-not-allowed', 'Not allowed', { method: 'addOAuthApp' });
}
if (!applicationParams.name || typeof applicationParams.name.valueOf() !== 'string' || applicationParams.name.trim() === '') {
throw new Meteor.Error('error-invalid-name', 'Invalid name', { method: 'addOAuthApp' });
}
if (
!applicationParams.redirectUri ||
typeof applicationParams.redirectUri.valueOf() !== 'string' ||
applicationParams.redirectUri.trim() === ''
) {
throw new Meteor.Error('error-invalid-redirectUri', 'Invalid redirectUri', {
method: 'addOAuthApp',
});
}
if (typeof applicationParams.active !== 'boolean') {
throw new Meteor.Error('error-invalid-arguments', 'Invalid arguments', {
method: 'addOAuthApp',
});
}
const application = {
...applicationParams,
redirectUri: parseUriList(applicationParams.redirectUri),
clientId: Random.id(),
clientSecret: Random.secret(),
_createdAt: new Date(),
_updatedAt: new Date(),
_createdBy: {View on GitHub (pinned to b2c16d5842)
Solutions
- Provide the real callback URL, e.g. https://app.example.com/oauth/callback
- Trim and non-empty-check redirectUri on the client before submit
- When multiple URIs are needed, send them comma- or newline-separated with at least one real URI
Example fix
// before
{ "name": "App", "active": true, "redirectUri": " " }
// after
{ "name": "App", "active": true, "redirectUri": "https://app.example.com/oauth/callback" } Defensive patterns
Strategy: type-guard
Validate before calling
// client-side: normalize and check the callback URL
const redirectUri = String(form.redirectUri ?? '').trim();
if (!/^https?:\/\/.+/.test(redirectUri)) throw new Error('A valid callback URL is required');
await post('/oauth-apps.create', { ...form, redirectUri }); Type guard
const isNonEmptyString = (v: unknown): v is string => typeof v === 'string' && v.trim().length > 0; const hasValidRedirectUri = (p: unknown): boolean => typeof p === 'object' && p !== null && isNonEmptyString((p as any).redirectUri);
Try / catch
try {
await addOAuthApp(params, uid);
} catch (error) {
if (error instanceof Meteor.Error && error.error === 'error-invalid-redirectUri') {
setFieldError('redirectUri', 'Enter at least one callback URL');
} else {
throw error;
}
} Prevention
- Trim redirectUri inputs and require an http(s) URL pattern
- Pre-fill the field with the client app's known callback URL when available
- Never assume redirectUri is optional
When it happens
Trigger: POST /api/v1/oauth-apps.create with redirectUri ' ' or '\n'; direct addOAuthApp call omitting redirectUri; textarea input containing only blank lines.
Common situations: Copy-pasting a callback URL that is actually empty/whitespace; form state reset between render and submit; programmatic callers assuming redirectUri is optional.
Related errors
- error-invalid-name
- error-invalid-arguments
- Type not supported
- invalid-params
- error-user-param-not-provided
AI-assisted analysis of RocketChat/Rocket.Chat@b2c16d5842 (2026-08-18).
Data as JSON: /api/errors/d5a1ad4dcf7986ba.
Report an issue: GitHub.