Apache Iceberg
Test Apache Iceberg tables through a REST catalog such as Polaris, Nessie, Unity Catalog, AWS Glue, or Amazon S3 Tables. The CLI loads each table with pyiceberg, scans it to Arrow, and runs the checks in DuckDB. For S3 Tables and Glue the requests are signed with your AWS credentials; see the reference.
1. Install
uv tool install --python python3.11 --upgrade 'datacontract-cli[iceberg]'
See Installation for pip, pipx, and Docker.
2. Authenticate
For Amazon S3 Tables or AWS Glue, use AWS credentials, not OAuth. The dedicated Amazon S3 Tables guide covers AWS_PROFILE, SSO login, the table bucket ARN, import/test commands, and a deliberate quality failure.
For OAuth-based REST catalogs, the catalog and data-file authentication are separate. Supply a client credential or bearer token as required by your catalog; data files on S3 use the same DATACONTRACT_S3_* options as the S3 source, unless the catalog vends credentials.
# catalog: one of
export DATACONTRACT_ICEBERG_CREDENTIAL=client_id:client_secret
export DATACONTRACT_ICEBERG_TOKEN=eyJ...
# data files (skip when the catalog vends credentials)
export DATACONTRACT_S3_ACCESS_KEY_ID=...
export DATACONTRACT_S3_SECRET_ACCESS_KEY=...
export DATACONTRACT_S3_REGION=eu-central-1
3. Create a contract from a table
datacontract import iceberg --catalog-url https://polaris.example.com/api/catalog \
--catalog main --namespace sales --table orders --output datacontract.yaml
The contract gets the table's schema, with map, list, and struct columns expanded, and a ready-to-test servers block:
servers:
- server: production
type: iceberg
catalog: main
catalogUrl: https://polaris.example.com/api/catalog
namespace: sales
datacontract import iceberg --source schema.json still imports from a schema file, without a server.
4. Test the actual data
datacontract test datacontract.yaml
Each schema object is one table in the namespace. A physicalName on the schema object names the table when it differs from the schema name; a name with a dot is used as the full identifier.
5. Let it catch a violation
Add a quality rule to the contract and run the test again:
quality:
- type: sql
description: No order without lines
query: SELECT count(*) FROM orders WHERE cardinality(lines) = 0
mustBe: 0
The query runs in DuckDB against the scanned table, so DuckDB's SQL dialect applies. Use the schema object's logical name in SQL, not its physicalName. The full selected tables are read into memory before the checks run.
Reference
All options and the data type handling: Apache Iceberg Reference.
Troubleshooting
catalogUrl is required— the server needs the REST endpoint incatalogUrl, orDATACONTRACT_ICEBERG_CATALOG_URL.Table 'sales.orders' was not found— checknamespace; the identifier the CLI asked for is in the message.- Expired AWS SSO session — run
aws sso login --profile "$AWS_PROFILE"again and retry. Check the selected account withaws sts get-caller-identity. 403while reading S3 Tables data files — verifys3tables:GetTableDataon the table and that temporary credentials include their session token. A successful catalog connection does not prove data-file access.403with other catalogs — check the data-file credentials (DATACONTRACT_S3_*) or the catalog's credential-vending configuration.