hcengineering/platform · warning · ApiError

No data to export

Error message

No data to export

What it means

After WorkspaceExporter.export runs into a fresh temp directory, createServer lists the directory; if it is empty, nothing matched the requested _class/query, so it throws this 400 'No data to export'. The export itself did not fail — it simply produced zero files.

Source

Thrown at services/export/pod-export/src/server.ts:420

        config?: TransformConfig
      } = req.body

      if (_class == null) {
        throw new ApiError(400, 'Missing required parameters')
      }

      const platformClient = await createPlatformClient(token)
      const txOperations = new TxOperations(platformClient, socialId)

      const exportDir = await fs.mkdtemp(join(tmpdir(), 'export-'))
      let archiveDir: string | undefined
      try {
        const exporter = new WorkspaceExporter(measureCtx, txOperations, storageAdapter, wsIds, config)
        await exporter.export(_class, exportDir, { format, attributesOnly: attributesOnly ?? false, query })

        const files = await fs.readdir(exportDir)
        if (files.length === 0) {
          throw new ApiError(400, 'No data to export')
        }

        let exportedFile: string
        if (files.length === 1) {
          // Single space exported: return its file directly.
          exportedFile = join(exportDir, files[0])
        } else {
          // Pack all spaces into a single archive so the sync endpoint can still return exactly one downloadable file.
          archiveDir = await fs.mkdtemp(join(tmpdir(), 'export-archive-'))
          const safeFormatToken = toSafeFormatFileToken(format)
          const archiveName = `export-${wsIds.uuid}-${safeFormatToken}-${Date.now()}.zip`
          exportedFile = join(archiveDir, archiveName)
          await saveToArchive(exportDir, exportedFile)
        }

        await new Promise<void>((resolve, reject) => {
          res.download(exportedFile, basename(exportedFile), (err) => {
            if (err != null && !res.headersSent) {

View on GitHub (pinned to 63e28dc964)

Solutions

  1. Verify _class is spelled exactly as in the model and that documents of that class exist in the target workspace.
  2. Relax or validate the query filter; first list documents of that class via the client API to confirm data exists.
  3. Check you are pointed at the intended workspace (wsIds comes from the token's login info).
  4. If multiple spaces export to separate files, confirm at least one space had matching data.

Example fix

// before
await exporter.export('contact:Company', dir, { format: 'json', query: { space: 'wrong-space' } })
// after
await exporter.export('contact:Company', dir, { format: 'json', query: { space: defaultSpaceId } })
Defensive patterns

Strategy: validation

Validate before calling

const existing = await client.findAll(model.classRefs[_class], { limit: 1, ...query })
if (existing.length === 0) {
  console.warn(`No ${_class} documents match query; export would return 'No data to export'`)
}

Type guard

null

Try / catch

try {
  const file = await exportWorkspace({ _class, query })
} catch (e) {
  if (e instanceof ApiError && e.message === 'No data to export') {
    return null // treat empty result as a valid, non-fatal outcome
  }
  throw e
}

Prevention

When it happens

Trigger: Exporting a _class that has no documents in the workspace, or a query filter that matches nothing; exporting with attributesOnly into a workspace lacking that class's data.

Common situations: Typos in the _class string (silently matching nothing); overly restrictive DocumentQuery (wrong space, wrong ids); running against a fresh/empty test workspace; class renamed in a newer model version.

Related errors


AI-assisted analysis of hcengineering/platform@63e28dc964 (2026-08-29). Data as JSON: /api/errors/923bc73ed935da4e. Report an issue: GitHub.