calcom/cal.diy · error · Error
Invalid credentials for userId ${credential.userId} and appI
Error message
Invalid credentials for userId ${credential.userId} and appId ${credential.appId}: ${parsedKey.error} What it means
Constructor of `CloseComCRMService` parses `credential.key` against `credentialSchema` (zod). If the key shape is wrong, it throws an Error whose message interpolates `credential.userId`, `credential.appId`, and the zod error. This stops CRM operations before they can send malformed auth to Close.
Source
Thrown at packages/app-store/closecom/lib/CrmService.ts:72
*
* Contact creation
* Every contact in Close.com need to belong to a Lead. When creating a contact in
* Close.com as part of this integration, a new generic Lead will be created in order
* to assign every contact created by this process, and it is named "From Cal.diy"
*/
class CloseComCRMService implements CRM {
private integrationName = "";
private closeCom: CloseCom;
private log: typeof logger;
constructor(credential: CredentialPayload) {
this.integrationName = "closecom_other_calendar";
this.log = logger.getSubLogger({ prefix: [`[[lib] ${this.integrationName}`] });
const parsedKey = credentialSchema.safeParse(credential.key);
if (!parsedKey.success) {
throw new Error(
`Invalid credentials for userId ${credential.userId} and appId ${credential.appId}: ${parsedKey.error}`
);
}
// Initialize CloseCom client based on credential type
if (parsedKey.data.encrypted) {
// API key authentication
const decrypted = symmetricDecrypt(parsedKey.data.encrypted, CALENDSO_ENCRYPTION_KEY);
const { api_key } = JSON.parse(decrypted);
this.closeCom = new CloseCom(api_key);
} else if (parsedKey.data.access_token) {
// OAuth authentication
this.closeCom = new CloseCom(parsedKey.data.access_token, {
refresh_token: parsedKey.data.refresh_token,
expires_at: parsedKey.data.expires_at,
isOAuth: true,
userId: credential.userId!,
});View on GitHub (pinned to 176037d0af)
Solutions
- Read the interpolated `parsedKey.error` in the thrown message — it lists the exact failing field paths.
- Have the user reconnect Close.com via OAuth so a fresh, schema-compliant credential is written.
- If a schema change caused it, write a migration to backfill/rename fields on existing `closecom_crm` credentials.
- Add a setup-time validation step so partial credentials are never persisted.
Defensive patterns
Strategy: validation
Validate before calling
const parsed = credentialSchema.safeParse(credential.key);
if (!parsed.success) {
const issues = parsed.error.issues.map((i) => i.path.join(".") + ": " + i.message).join("; ");
throw new Error(`Close.com credential invalid: ${issues}`);
} Type guard
function isCloseCredentialKey(k: unknown) {
return credentialSchema.safeParse(k).success;
} Try / catch
try {
new CloseComCRMService(credential);
} catch (e) {
if (e instanceof Error && /Invalid credentials/.test(e.message)) {
await flagCredentialForReconnection(credential.id);
return null;
}
throw e;
} Prevention
- Validate the credential key shape at OAuth-save time.
- Run schema backfills when extending credentialSchema.
- Surface zod issue paths in the error message for fast triage.
- Add a setup wizard that blocks incomplete credential persistence.
When it happens
Trigger: A Close.com credential row whose `key` is missing required fields (e.g. no `access_token`/`refresh_token`/`expires_at` for OAuth, or no `encrypted` for API-key mode), has extra/renamed fields, or values of the wrong type — typically after an incomplete OAuth save or a schema migration.
Common situations: OAuth callback persisted a partial credential (token exchange succeeded but `key` written incompletely); schema changed without backfill; manual DB edit; older credential format from a previous app version.
Understand the failure class
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- No valid authentication method found
- Cal.diy: Invalid BTCPay credentials
- ${appSlug} not connected.
- parsedQuery.error.message
- Invalid refreshed tokens were returned
AI-assisted analysis of calcom/cal.diy@176037d0af (2026-08-12).
Data as JSON: /api/errors/7f6802aff89e7410.
Report an issue: GitHub.