{"record":{"id":"cf930887bee33baa","repo":"calcom/cal.diy","slug":"no-valid-authentication-method-found","errorCode":null,"errorMessage":"No valid authentication method found","messagePattern":"No valid authentication method found","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/app-store/closecom/lib/CrmService.ts","lineNumber":92,"sourceCode":"      );\n    }\n\n    // Initialize CloseCom client based on credential type\n    if (parsedKey.data.encrypted) {\n      // API key authentication\n      const decrypted = symmetricDecrypt(parsedKey.data.encrypted, CALENDSO_ENCRYPTION_KEY);\n      const { api_key } = JSON.parse(decrypted);\n      this.closeCom = new CloseCom(api_key);\n    } else if (parsedKey.data.access_token) {\n      // OAuth authentication\n      this.closeCom = new CloseCom(parsedKey.data.access_token, {\n        refresh_token: parsedKey.data.refresh_token,\n        expires_at: parsedKey.data.expires_at,\n        isOAuth: true,\n        userId: credential.userId!,\n      });\n    } else {\n      throw new Error(\"No valid authentication method found\");\n    }\n  }\n\n  closeComUpdateCustomActivity = async (uid: string, event: CalendarEvent) => {\n    const customActivityTypeInstanceData = await getCustomActivityTypeInstanceData(\n      event,\n      calComCustomActivityFields,\n      this.closeCom\n    );\n    // Create Custom Activity type instance\n    const customActivityTypeInstance = await this.closeCom.activity.custom.create(\n      customActivityTypeInstanceData\n    );\n    return this.closeCom.activity.custom.update(uid, customActivityTypeInstance);\n  };\n\n  closeComDeleteCustomActivity = async (uid: string) => {\n    return this.closeCom.activity.custom.delete(uid);","sourceCodeStart":74,"sourceCodeEnd":110,"githubUrl":"https://github.com/calcom/cal.diy/blob/176037d0afbe572f870a3c702985e7cd83fe6c0c/packages/app-store/closecom/lib/CrmService.ts#L74-L110","documentation":"Branching auth logic in the `CloseComCRMService` constructor: after parsing, it tries API-key auth via `parsedKey.data.encrypted`, then OAuth via `parsedKey.data.access_token`; if neither is present it throws this Error. The credential passed schema validation but contains no usable auth method.","triggerScenarios":"Credential `key` satisfies the zod schema (both `encrypted` and `access_token` are optional) but contains neither — e.g. a credential saved as an empty/partial object, or a future credential type that the constructor doesn't yet handle.","commonSituations":"Credential row written with placeholder/empty values during a failed setup; schema allows `{}` but no auth fields populated; race between credential creation and token persistence.","solutions":["Have the user reconnect Close.com so the credential stores either a valid `encrypted` API key or a full OAuth token set.","Tighten `credentialSchema` to require at least one auth method (use `z.union(...)` or `.refine()`) so this state is rejected at parse time with a clearer error.","Audit where empty credentials can be persisted (failed OAuth save path) and add a guard there.","Log the credential `id`/`userId` when this throws so support can find the offending row."],"exampleFix":"// before\nconst parsedKey = credentialSchema.safeParse(credential.key);\nif (!parsedKey.success) { /* ... */ }\n// ... later\n} else {\n  throw new Error(\"No valid authentication method found\");\n}\n\n// after\nconst parsedKey = credentialSchema\n  .refine((k) => Boolean(k.encrypted) || Boolean(k.access_token), {\n    message: \"No valid authentication method found\",\n  })\n  .safeParse(credential.key);\nif (!parsedKey.success) {\n  throw new Error(\n    `Invalid credentials for userId ${credential.userId} and appId ${credential.appId}: ${parsedKey.error}`\n  );\n}","handlingStrategy":"validation","validationCode":"const parsed = credentialSchema\n  .refine((k) => Boolean(k.encrypted) || Boolean(k.access_token), { message: \"No auth method\" })\n  .safeParse(credential.key);\nif (!parsed.success) throw new Error(`Credential unusable: ${parsed.error}`);","typeGuard":"function hasCloseAuthMethod(k: unknown): boolean {\n  return !!k && typeof k === \"object\" && (Boolean((k as any).encrypted) || Boolean((k as any).access_token));\n}","tryCatchPattern":"try {\n  new CloseComCRMService(credential);\n} catch (e) {\n  if (e instanceof Error && /No valid authentication method/.test(e.message)) {\n    await promptUserReconnect(credential.userId, \"closecom\");\n    return null;\n  }\n  throw e;\n}","preventionTips":["Make the schema require at least one auth method via refine/union.","Block empty credential persistence at the OAuth save boundary.","Add a credential-health job that flags rows with no auth method.","Log credential id (not key) when this throws to locate the bad row."],"tags":["validation","credentials","authentication","closecom","crm"],"backgroundTag":null,"analyzedSha":"176037d0afbe572f870a3c702985e7cd83fe6c0c","analyzedAt":"2026-08-12T19:12:41.464Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}