Nov 07, 2025·7 min read

Audit third-party integrations for silent failures

Learn how to audit third-party integrations in Slack, Google, and GitHub to catch missing scopes, expired tokens, and permission mismatches early.

Audit third-party integrations for silent failures

Why third-party integrations fail silently

A silent failure is when an integration stops doing its job but nobody gets a clear error. The app loads. Buttons still work. Yet the outcome never shows up: no Slack message, no calendar event, no GitHub check, no data sync.

People report it as “it used to work” because the break is often delayed. It can run fine for days or weeks, then stop after a token expires, a permission policy changes, or someone reinstalls the app differently.

The impact is easy to miss because it looks like “nothing happened.” Watch for patterns like notifications that stop arriving, sync gaps where only some records update, missing fields or missing destinations (channels, repos, folders), or actions that work in one workspace but fail in another.

Most silent failures come from three roots:

  • Tokens: the key that proves the integration is allowed to act.
  • Scopes: the specific access the app asked for, like reading channels or writing messages.
  • Permission models: the platform and organization rules that decide what’s actually allowed.

Treat “no error” as a clue, not reassurance. If the UI says “connected” but nothing happens, assume something changed outside your code.

Tokens in plain language: what expires and what gets revoked

Token problems are the most common cause of silent failures. “Still saved in the database” does not mean “still valid.”

An access token is the short-term key your app uses on every API call. Many providers expire it.

A refresh token is the longer-term renewal card. Your app trades it for a new access token without forcing the user to sign in again. If you never stored a refresh token (or lost it), your integration often works at first and then goes quiet later.

Tokens usually become invalid for a few predictable reasons:

  • Time-based expiry (access tokens time out; refresh tokens can also expire)
  • The user revokes access
  • An admin removes the app, changes org policy, or disables the integration
  • Security events like password resets, SSO changes, or suspicious-login protections
  • Secret rotation that accidentally breaks token exchange

Where you store tokens affects both security and reliability. Client-side storage (like localStorage) can be cleared, copied, or blocked by browser rules. Server-side storage is usually safer, but only if it’s treated like a password: encrypted at rest, tightly limited access, and never printed in logs.

Token rotation should feel boring to users. Aim for “overlap, then cut over”: keep the old token working for a short window while you start using the new one, and provide a clear re-auth path when renewal fails.

Example: a Slack alert bot posts fine for a week, then goes quiet. The access token expired, and the app never stored a refresh token, so it can’t renew. The real fix isn’t just “get a new token.” It’s storing tokens safely and handling renewals (and failures) on purpose.

Scopes vs permissions: the mismatch that causes surprise failures

Scopes are what an integration asks for. They show up in the OAuth consent screen or app settings as “This app wants to read messages” or “This app wants to write to issues.”

Permissions are what the user or organization can actually do. Someone can approve a scope, and the platform can still block the action because of org rules, role limits, or resource access.

That’s why “the app has the scope” can still fail. The token says the app is allowed to try, but the environment can still say no.

Common examples:

  • Slack: your app has chat:write, but it isn’t in the channel, or org settings restrict posting.
  • Google: you have a Drive scope, but the account can’t access a shared drive, or an admin blocks the app for the domain.
  • GitHub: your app requests repo permissions, but org policies limit third-party access, or the app isn’t installed on the right repos.

When something breaks, separate “what the app requested” from “what the environment permits.” Two questions usually uncover the gap:

  1. Did we request the scopes we need for the feature as it exists today?
  2. Does this user/org have access to the exact workspace, folder, repo, or channel involved?

Least privilege is good, but it has a catch: if you remove scopes without checking every feature path, you can create silent failures that only show up in edge cases.

A practical habit is to keep a short scope map for each feature: what it does, which scopes it needs, and which org rules could block it.

Make an integration inventory before you debug

Silent failures are hard to fix if you don’t know what’s connected to what. Before changing code, build a simple inventory. It turns a guessing game into a checklist.

List every external system your app touches, even “small” ones: Slack, Google, GitHub, email providers, analytics, payments, and any internal admin tools. Many mystery bugs happen because an integration exists in staging but not in production, or because production points at a different workspace/org than the one you tested.

For each integration, write down who installed it, which workspace/org it belongs to, and what it’s supposed to do. “Slack alerts” is too vague. Note whether it posts to one channel or many, reads messages, creates channels, manages webhooks, or syncs data.

Also capture the auth model, because your audit steps depend on it. OAuth installs, GitHub Apps, personal access tokens, and Google service accounts can all power similar features, but they fail in different ways.

A one-page inventory template:

  • System + account (Slack workspace, Google project, GitHub org)
  • Owner (who installed it and who can re-install it)
  • Auth method (OAuth, GitHub App, PAT, service account)
  • Expected actions (post messages, sync calendar, read repos)
  • Where it runs (prod, staging, local; plus the environment variables used)

Example: a founder inherits an app where Slack notifications sometimes stop. The inventory shows the Slack app was installed by a contractor in a different workspace than production, so the “working” token was never tied to the real channel.

Step-by-step: a practical audit you can repeat

Build an Integration Inventory
Get a practical checklist of what is installed where and what each integration should do.

Most silent failures are boring: an app got uninstalled, a token expired, or someone changed approval rules. The fastest audits follow the same small routine every time.

Start by confirming the integration is still real where it lives:

  • The app is installed
  • It’s connected to the correct workspace/org
  • Production is pointing at production (not staging), and environment variables match

Then run five checks, in order:

  • Existence and ownership: Who installed it, and do they still have access?
  • Token health: Is the token expired, revoked, or unused for weeks (a clue it’s not being called)?
  • Scope match: Compare what the app needs today vs what it was granted.
  • Permission model: Confirm required user roles, org policies, app approvals, or admin settings still allow it.
  • One real end-to-end test: Trigger a real event and verify the side effect where it should appear.

When you compare scopes, don’t rely on what the code assumes. Write down the exact actions the integration must perform (post a message, read a file, open an issue) and map each action to a granted scope.

Then make the next failure loud. At minimum, alert on repeated 401/403 errors, alert when refresh fails, and alert when a job runs but produces zero output.

Slack audits: scopes, channel access, and installer issues

Slack integrations often look “healthy” because the app is still installed, but the bot quietly loses the ability to read a channel, post a message, or fetch user data.

Start with basics that get overlooked:

  • Which workspace the app is installed in
  • Which environment (prod vs staging) is using that installation
  • Whether the token you’re using actually belongs to the expected workspace

Next, match features to OAuth scopes. Posting alerts usually needs chat:write. Looking up users may need users:read. Reading channels and reacting to events can require channel scopes. Missing a single scope can become “nothing happens” if your code swallows errors or logs them somewhere nobody checks.

Channel access is another common trap. Posting to a private channel isn’t the same as posting to a public one. The bot must be invited, and some workspaces restrict app access to private channels entirely. If alerts stopped in one channel but still work in another, suspect channel membership or a policy change.

Installer issues cause silent failures too. Many Slack apps are authorized by one person. If that person leaves or their role changes, the app can lose access depending on workspace rules.

A simple Slack audit flow:

  • Confirm workspace, app, and environment variables match what production expects.
  • Check current scopes against the exact actions your app performs.
  • Verify the bot is a member of every target channel (especially private ones).
  • Identify who authorized the app and whether they’re still active.
  • Review what changed after the last reinstall, since scopes and permissions can shift.

Google integrations often fail without clear errors because the “yes” you got during setup isn’t always the “yes” you still have today.

Start with the OAuth consent screen. If the app is still in testing, unverified, or tied to a project that changed owners, users can lose access without anyone touching your code. Check that it’s published for the right user type (internal vs external) and that app details still match what Google expects.

Then focus on refresh tokens. Many apps work fine for an hour (access token lifetime), then stop after the refresh token is revoked, expires due to inactivity, or gets blocked by policy. This is why developers often see “works on my machine”: they keep re-consenting.

High-value checks to repeat:

  • Consent screen status (published, verification, user type)
  • Refresh tokens exist and refresh still succeeds
  • Google Workspace admin rules (app access control and user consent)
  • Service account setup and domain-wide delegation (if used)
  • Sensitive scopes, especially if policies or verification changed

Workspace admin controls are a common surprise. An admin can restrict third-party apps, block user consent, or limit which OAuth client IDs are allowed. The integration may keep “connecting” for one user but fail for everyone else.

Service accounts add another layer: domain-wide delegation must be enabled, the admin must approve the client, and the delegated scopes must match what your code requests. A single missing scope can look like a data bug.

GitHub audits: app type, org policies, and scope drift

Harden Security Basics
We harden token storage and remove exposed secrets in AI generated codebases.

GitHub integrations often fail quietly because the “thing that authenticates” isn’t what you think it is. First, name the auth type:

  • A GitHub App (installed on an org or repos)
  • An OAuth App (user-based)
  • A personal access token (PAT)

Each one breaks differently, and the fix changes with it.

What to verify inside a GitHub org

Confirm what the integration is allowed to touch. With GitHub Apps, permissions are split into areas (contents, issues, pull requests, checks, workflows) and can be read-only or read/write. Also check whether the app is installed on all repositories or only specific repos. A common silent failure is adding a new repo while the app still only has access to the old repo list.

Then look for org controls that block access without obvious errors. Many organizations enforce SAML SSO. When that happens, user tokens may need explicit SSO authorization, and automations can stop when the token owner leaves. Another blocker is org rules that require admin approval for app installations or new permission requests.

Watch for scope drift: the code starts using a new API (for example, creating checks or posting PR comments), but the app still has the older, smaller permission set. Calls fail, get retried, and disappear into logs.

A fast GitHub audit:

  • Identify auth type and who owns it (service account vs a real employee).
  • Confirm current permissions match what the integration actually does.
  • Verify installation coverage (which orgs and repos are included).
  • Check org policies: SSO enforcement, app approval rules, restrictions.
  • Review recent “quick fixes” where someone swapped tokens during a migration.

Example: the Slack alert bot that quietly stops posting

A common silent failure looks like this: your product posts an alert to Slack every time a background job fails. Everyone gets used to it, so nobody checks the dashboard as often.

Then one week, jobs still fail, but Slack stays quiet. The problem isn’t the jobs. It’s the integration.

A frequent pattern: the person who installed the Slack app (often a contractor or early team member) leaves. Later, their account is deactivated, or the app gets removed during a workspace cleanup. Slack revokes the token, but your app keeps running and keeps trying to post. If your code only logs the error to a server log (or swallows it), nobody sees the break.

A simple audit path usually finds it quickly:

  • Verify the app is installed in the right Slack workspace.
  • Confirm who installed it (and whether that account still exists).
  • Check scopes against what you’re trying to do.
  • Validate channel access: is the bot in the channel, and is the channel private?
  • Send a test alert now and watch the full request/response.

The fix is usually straightforward: re-authorize with a stable owner (not a personal account that can disappear), confirm Slack scopes match your real actions, and re-invite the bot to the target channels.

To prevent a repeat, add one lightweight heartbeat (like a daily test message to a low-noise channel) plus monitoring that alerts you when Slack returns an auth or permission error.

Common mistakes that keep failures hidden

Rescue an AI Built App
Turn an AI generated prototype into production ready code with expert verification.

Silent failures usually happen because an integration looks fine on the surface. The request returns something that seems OK, but the side effect (post a message, create a file, open a PR) never happens.

One trap is treating a 200 response as proof the job worked. Some APIs return success for accepted work and fail later (rate limits, missing channel access, policy blocks). If you don’t verify the side effect, you can miss the failure for days.

Another mistake is catching errors but hiding them. Teams often log the exception and keep going, so users see “everything is fine” while the integration is broken. If an integration step is required (payments, notifications, deployments), errors need to alert a real person.

Scopes and consent are also easy to misunderstand. You might request new Slack app scopes or Google OAuth permissions in code, but nothing changes until the app is re-installed or the user re-consents. That creates a mismatch: your code assumes new access, but production tokens still lack it.

Mixing user permissions with app permissions creates “works on my account” bugs. A developer’s user token can access a private Slack channel or a GitHub repo, while the real app installation can’t.

Token storage choices can hide problems and create risk:

  • Tokens stored client-side get cleared with no record.
  • Tokens leak into logs, making debugging harder.
  • Tokens get shared across environments, so staging changes break production.

Quick checklist and next steps

Silent failures usually come down to one of three things: the app is no longer installed or approved, the token stopped working, or the integration is asking for the wrong access for what it tries to do.

Before changing code, do a fast pass on the basics:

  • Confirm the integration still shows as installed and approved in the workspace/org, and that it’s connected to the account you expect.
  • Trigger a normal re-auth or token refresh (no shortcuts). If it can’t re-auth, treat it like an access problem, not a code bug.
  • Compare granted scopes/permissions to what the feature needs today, not what it needed when you first built it.
  • Check for policy changes: SSO enforcement, app approval rules, restricted repos, admin consent requirements.
  • Look for silent error handling: empty catch blocks, ignored non-200 responses, retries that never alert, or missing logs for auth failures.

Then write down the minimal access the integration needs: scopes, resources (channels, drives, repos), and who must install it (user vs admin). Schedule a monthly mini-audit: one real test action per integration and one place to review failures.

If you inherited an AI-generated app where integrations are flaky or unsafe, FixMyMess (fixmymess.ai) can do a free code audit to pinpoint token handling, scope gaps, and permission edge cases, then repair them so failures are visible and recovery is predictable.