cube-js/cube · error · Error

Unable to UNLOAD table, there are no files in S3 storage

Error message

Unable to UNLOAD table, there are no files in S3 storage

What it means

A sentinel guard in RedshiftDriver.unload: after Redshift UNLOADs the table to S3, extractUnloadedFilesFromS3 lists the exported objects and the list came back empty — no manifest/CSV files exist at the export path. This usually means the UNLOAD wrote nothing (empty result with no files emitted), the S3 path/prefix is wrong, or the credentials used for listing lack access to the bucket prefix. It detects a broken unload-export round trip rather than a query error.

Source

Thrown at packages/cubejs-redshift-driver/src/RedshiftDriver.ts:507

          csvFile: [],
          types
        };
      }

      const csvFile = await this.extractUnloadedFilesFromS3(
        {
          credentials: (keyId && secretKey) ? {
            accessKeyId: keyId,
            secretAccessKey: secretKey,
          } : undefined,
          region,
        },
        bucketName,
        exportPathName,
      );

      if (csvFile.length === 0) {
        throw new Error('Unable to UNLOAD table, there are no files in S3 storage');
      }

      return {
        exportBucketCsvEscapeSymbol: this.config.exportBucketCsvEscapeSymbol,
        csvFile,
        types
      };
    } finally {
      conn.removeAllListeners('notice');
      await this.pool.release(conn);
    }
  }

  public capabilities(): DriverCapabilities {
    return {
      incrementalSchemaLoading: true,
    };
  }

View on GitHub (pinned to 7d981676b3)

Solutions

  1. Verify the source table actually contains rows (SELECT COUNT(*))
  2. Confirm bucketName/region/prefix configuration matches what UNLOAD was authorized to write to
  3. Check IAM policy allows s3:ListBucket/s3:GetObject on the export prefix
  4. Retry — transient S3 listing lag right after unload can briefly return an empty listing
Defensive patterns

Strategy: retry

Validate before calling

// pre-check data exists before exporting
const [{ count }] = await driver.query('SELECT COUNT(*) AS count FROM ' + tableName);

Try / catch

try {
  return await driver.unload(tableName, options);
} catch (e) {
  if (/no files in S3 storage/.test(e.message)) {
    // check table row count and S3 prefix/IAM config, then retry once
  }
  throw e;
}

Prevention

When it happens

Trigger: unload() runs the UNLOAD statement and the subsequent S3 listObjectsV2 for bucketName/exportPathName returns zero csvFile entries — e.g. the query produced zero rows (Redshift writes no files), or the object listing targets the wrong bucket/prefix/region.

Common situations: Pre-aggregation/table with no data; mismatch between the S3 prefix used in UNLOAD and the one being listed; IAM permissions hiding objects; eventual-consistency lag right after UNLOAD.

Related errors


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