cube-js/cube · error · UserError

Can't fetch metrics from Dbt Cloud: ${res.errors[0].message}

Error message

Can't fetch metrics from Dbt Cloud: ${res.errors[0].message}

What it means

loadMetricCubesFromDbtCloud executes a GraphQL query against the Dbt Cloud Discovery API (with a bearer token and jobId). If the response body contains a non-empty errors array, the first error message from the API is surfaced wrapped in this UserError.

Source

Thrown at packages/cubejs-dbt-schema-extension/src/Dbt.ts:173

      const modelName = match[1];
      metricDef.model = modelName.indexOf('.') !== -1 ? modelName : `model.${metricDef.package_name}.${modelName}`;
    });
    return this.loadMetricCubesFromNormalizedManifest(manifest, manifestPath, options);
  }

  public async loadMetricCubesFromDbtCloud(jobId: string | number, authToken: string, options: DbtLoadOptions): Promise<{ [cubeName: string]: any }> {
    const response = await fetch('https://metadata.cloud.getdbt.com/graphql', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        Accept: 'application/json',
        Authorization: `Bearer ${authToken}`
      },
      body: JSON.stringify({ query: loadModelsQuery, variables: { jobId } })
    });
    const res = <GraphqlResponse>(await response.json());
    if (res.errors && res.errors.length > 0) {
      throw new UserError(`Can't fetch metrics from Dbt Cloud: ${res.errors[0].message}`);
    }
    const manifest: DbtManifest = {
      metrics: res.data.metrics.map(metricDef => ({
        [metricDef.uniqueId]: {
          unique_id: metricDef.uniqueId,
          name: metricDef.name,
          model: metricDef.model.uniqueId,
          // eslint-disable-next-line camelcase
          package_name: metricDef.packageName,
          type: metricDef.type,
          sql: metricDef.sql,
          dimensions: metricDef.dimensions,
          timestamp: metricDef.timestamp,
        }
      })).reduce((a, b) => ({ ...a, ...b }), {}),
      nodes: res.data.models.map(modelDef => ({
        [modelDef.uniqueId]: {
          database: modelDef.database,

View on GitHub (pinned to 7d981676b3)

Solutions

  1. Verify the Dbt Cloud auth token is valid and has access to the job/account (test with a curl to the Discovery API)
  2. Check the jobId passed in options corresponds to an existing, successful job in the same account
  3. Read the inner errors[0].message for the actual API reason (auth, not found, validation) and fix accordingly
  4. Confirm the Dbt Cloud account/environment has the Discovery API/metrics enabled
  5. Upgrade the extension if the Discovery API schema changed

Example fix

null
Defensive patterns

Strategy: try-catch

Validate before calling

const res = await fetch('https://cloud.getdbt.com/api/graphql/v2', {
  method: 'POST',
  headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' },
  body: JSON.stringify({ query: 'query { __typename }' })
});
if (!res.ok) throw new Error(`Dbt Cloud token/jobId check failed: ${res.status}`);

Type guard

function hasGraphqlErrors(res) {
  return Array.isArray(res?.errors) && res.errors.length > 0;
}

Try / catch

try {
  await dbt.loadMetricCubesFromDbtCloud(projectPath, { jobId, authToken });
} catch (e) {
  if (e.message.startsWith("Can't fetch metrics from Dbt Cloud")) {
    console.error('Dbt Cloud API error:', e.message); // inspect inner API message
  } else { throw e; }
}

Prevention

When it happens

Trigger: Calling loadMetricCubesFromDbtCloud with an invalid/expired Dbt Cloud API token, a jobId that doesn't exist or isn't accessible to the token, a GraphQL query error (e.g. metrics not exposed by the Discovery API for that job/account), or Dbt Cloud-side validation errors.

Common situations: Expired or rotated Dbt Cloud service tokens; wrong jobId in configuration; the job's environment lacking Discovery API access or the metrics feature; account/permission changes; Dbt Cloud API deprecations changing the schema the extension queries.

Understand the failure class

Background: "API request failed": what wrapped HTTP errors from external APIs mean and how to find the real cause — this error's family across 29 libraries.

Related errors


AI-assisted analysis of cube-js/cube@7d981676b3 (2026-09-02). Data as JSON: /api/errors/f29c64559f26f2a8. Report an issue: GitHub.