langgenius/dify · error · Error

export response missing data field

Error message

export response missing data field

What it means

Raised by ExternalKnowledgeHitTestingApi.post (POST /datasets/{dataset_id}/external-hit-testing) when DatasetService.get_dataset returns None for the given dataset_id. The lookup is by primary key only (no tenant scoping at this line), so the ID simply does not exist in the datasets table. RBAC and permission checks run only after this existence check, so a 404 here precedes any 403. Werkzeug NotFound maps to HTTP 404.

Source

Thrown at cli/src/api/app-dsl.ts:50

    })
  }

  async exportDsl(appId: string, query?: ExportQuery): Promise<string> {
    const resp = await this.orpc.apps.byAppId.dsl.get({
      params: { app_id: appId },
      query:
        query !== undefined
          ? {
              include_secret: query.includeSecret,
              workflow_id: query.workflowId,
            }
          : undefined,
    })
    // The response schema is an open object {"data": "<yaml string>"}; the
    // contract generator marks it as loose because the backend annotation
    // does not narrow the shape. Extract `data` directly.
    const data = (resp as Record<string, unknown>).data
    if (typeof data !== 'string') throw new Error('export response missing data field')
    return data
  }

  async checkDependencies(appId: string): Promise<CheckDependenciesResult> {
    return this.orpc.apps.byAppId.dependencies.check.get({
      params: { app_id: appId },
    })
  }
}

View on GitHub (pinned to ef8544b173)

Solutions

  1. Verify the dataset_id exists: call GET /console/api/datasets/{dataset_id} and confirm a 200 before issuing the hit-testing POST.
  2. If the dataset was deleted, create a new external knowledge dataset and update the calling code/UI to use the new ID.
  3. Reload the knowledge list in the console UI to refresh cached IDs before retrying.

Example fix

// before
const res = await fetch(`/console/api/datasets/${staleDatasetId}/external-hit-testing`, { method: 'POST', body: ... });
// after
const exists = await fetch(`/console/api/datasets/${datasetId}`).then(r => r.ok);
if (!exists) { throw new Error('Dataset missing — refresh the knowledge list'); }
const res = await fetch(`/console/api/datasets/${datasetId}/external-hit-testing`, { method: 'POST', body: ... });
Defensive patterns

Strategy: validation

Validate before calling

async function datasetExists(client, datasetId: string): Promise<boolean> {
  const r = await client.get(`/console/api/datasets/${datasetId}`);
  return r.status === 200;
}
// call before POST /datasets/{id}/external-hit-testing
if (!(await datasetExists(client, datasetId))) {
  throw new Error(`Dataset ${datasetId} does not exist`);
}

Type guard

function isValidDatasetId(id: string): boolean {
  // UUID v4 format expected by the <uuid:dataset_id> route converter
  return /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(id);
}

Try / catch

try {
  await client.post(`/datasets/${datasetId}/external-hit-testing`, payload);
} catch (e) {
  if (e.response?.status === 404) {
    await refreshDatasetList();  // clear stale id
    return;
  }
  throw e;
}

Prevention

When it happens

Trigger: POST /console/api/datasets/{dataset_id}/external-hit-testing with a dataset_id that was deleted, never existed, or was copied incorrectly (e.g. stale URL copied from another environment). Also triggered when testing external knowledge retrieval against a dataset whose ID has a valid UUID format but no matching row.

Common situations: Stale dataset_id cached in the frontend after the dataset was deleted; cross-environment paste of a URL containing a dataset_id from dev into staging; race where the dataset is deleted between page load and the hit-testing request.

Related errors


AI-assisted analysis of langgenius/dify@ef8544b173 (2026-08-12). Data as JSON: /api/errors/b457e4fb0f3dda0b. Report an issue: GitHub.