transloadit/uppy · error · Error

Received no remote credentials

Error message

Received no remote credentials

What it means

When Companion is configured with a credentialsUrl (custom/remote credentials service), it POSTs the provider name and request parameters to that endpoint and expects a JSON credentials object back. If the response body is missing or not a plain object, this error is thrown before the error is logged and re-raised to the caller.

Source

Thrown at packages/@uppy/companion/src/server/provider/credentials.ts:32

/**
 * @param url
 * @param providerName
 * @param credentialRequestParams - null asks for default credentials.
 */
async function fetchKeys(
  url: string,
  providerName: string,
  credentialRequestParams: unknown | null,
) {
  try {
    const { credentials } = await got
      .post(url, {
        json: { provider: providerName, parameters: credentialRequestParams },
      })
      .json<{ credentials?: CredentialsFetchResponse }>()

    if (!isRecord(credentials))
      throw new Error('Received no remote credentials')

    return credentials
  } catch (err) {
    logger.error(err, 'credentials.fetch.fail')
    throw err
  }
}

/**
 * Fetches for a providers OAuth credentials. If the config for that provider allows fetching
 * of the credentials via http, and the `credentialRequestParams` argument is provided, the oauth
 * credentials will be fetched via http. Otherwise, the credentials provided via companion options
 * will be used instead.
 *
 * @param providerName the name of the provider whose oauth keys we want to fetch (e.g onedrive)
 * @param companionOptions the companion options object
 * @param credentialRequestParams the params that should be sent if an http request is required.
 */

View on GitHub (pinned to 5d4dedd02a)

Solutions

  1. curl -X POST the credentials endpoint with the same payload and confirm it returns a JSON object with the provider's keys/secrets
  2. Verify the credentialsUrl path, protocol, and any auth headers are correct in Companion config
  3. Make the endpoint return a top-level JSON object (not wrapped in data) with valid status codes
  4. Check the credentials service logs — Companion logs this as credentials.fetch.fail with the underlying error

Example fix

// before (credentials service)
app.post('/credentials', (req, res) => res.json({ data: { key: k, secret: s } }))

// after
app.post('/credentials', (req, res) => res.json({ key: k, secret: s }))
Defensive patterns

Strategy: try-catch

Validate before calling

// Health-check the credentials service before relying on it
const res = await fetch(credentialsUrl, {
  method: 'POST',
  headers: { 'content-type': 'application/json' },
  body: JSON.stringify({ provider: 'drive', parameters: {} }),
})
const json = await res.json().catch(() => null)
if (!json || typeof json !== 'object') throw new Error('credentials service unhealthy')

Type guard

function isCredentialsRecord(v: unknown): v is Record<string, unknown> {
  return typeof v === 'object' && v !== null && !Array.isArray(v)
}

Try / catch

try {
  const creds = await companion.getProviderCredentials()
} catch (err) {
  if (err instanceof Error && err.message === 'Received no remote credentials') {
    alertProviderOps('credentials service down')
  }
  throw err
}

Prevention

When it happens

Trigger: Configuring companionOptions.providerOptions.credentialsUrl (or per-provider custom credentials) to an endpoint that returns an empty body, a JSON array/string instead of an object, a 200 page with HTML (mis-routed endpoint), or one that crashes and returns nothing parseable.

Common situations: The credentials microservice is down or mis-deployed, the URL has a typo so a generic 200 catch-all page responds, the endpoint returns { data: {...} } wrapping instead of a top-level object, or auth between Companion and the service silently fails.

Related errors


AI-assisted analysis of transloadit/uppy@5d4dedd02a (2026-08-28). Data as JSON: /api/errors/7bc2815425c396f1. Report an issue: GitHub.