storage: Honor write.data.path when placing Iceberg data files - #38412
storage: Honor write.data.path when placing Iceberg data files#38412patrickwwbutler wants to merge 1 commit into
Conversation
The Iceberg sink hardcoded its data-file location to `<table location>/data`,
ignoring the `write.data.path` property the catalog advertises. Catalogs that
manage their own storage layout reject a commit whose data files sit outside
that path.
Unity Catalog is the case that surfaced this. Its Iceberg tables are backed by
Delta, so an Iceberg commit has to be translated into a Delta commit that
registers the incoming data files. Files written under `<location>/_iceberg/data`
are outside the path it manages, and the commit fails server-side:
500 Internal Server Error
{"error":{"message":"Could not process table operation. [ErrorCode: 2012]",
"type":"ServiceFailureException","code":500}}
Nothing in the request identifies the cause, and the sink retries until it
stalls. Comparing against a client whose commits Unity Catalog accepts showed
its data files at the table root, matching the `write.data.path` the table
advertises, while ours sat a directory deeper.
Prefer `write.data.path`, then `write.folder-storage.path`, and only fall back
to the previous `<location>/data` heuristic when neither is set. That keeps the
S3 Tables workaround intact, since it exists precisely for a catalog that does
not advertise a data path. `DefaultLocationGenerator::new` reads the same two
properties but its fallback lacks that correction, so the choice is explicit
here rather than delegated.
Also logs the resolved location at debug, since a wrong data path otherwise
only manifests as an opaque catalog error at commit time.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
| // fallback misses the S3 Tables correction below, so choose explicitly. | ||
| let data_location = table_metadata | ||
| .properties() | ||
| .get("write.data.path") |
There was a problem hiding this comment.
Just to confirm this doesn't show up for AWS? What testing/validation did we have covering this
| // referencing files under `<location>/data` with a 500. | ||
| // | ||
| // `DefaultLocationGenerator::new` reads these same properties, but its | ||
| // fallback misses the S3 Tables correction below, so choose explicitly. |
There was a problem hiding this comment.
style nit: Can we shorten this a bit? Too verbose for my taste. Not a blocking issue though.
Proposed replacement:
// Unity Catalog required respecting "write.data.path" while AWS does
// not provide "write.data.path" and required a hacky workaround.
QA LLM Review1. MEDIUM --
|
The Iceberg sink hardcoded its data-file location to
<table location>/data, ignoring thewrite.data.pathproperty the catalog advertises. Catalogs that manage their own storage layout reject a commit whose data files sit outside that path.How this surfaced
Unity Catalog's Iceberg tables are backed by Delta, so an Iceberg commit must be translated into a Delta commit that registers the incoming data files. Files written under
<location>/_iceberg/dataare outside the path it manages, and the commit fails server-side with nothing in the response identifying the cause:The sink retries five times and then stalls, so the symptom is a sink that writes data files happily and never commits.
Comparing against a client whose commits Unity Catalog accepts (DuckDB, writing to the same catalog) showed the difference: its data file sat at the table root, matching the advertised
write.data.path, and its commit produced a new_delta_logentry. Ours sat a directory deeper under_iceberg/data, and no Delta commit was ever created.The request body was not the problem — with the
mz-*snapshot properties removed and theassert-ref-snapshot-idrequirement dropped, an otherwise byte-standard commit still failed. Only the file placement mattered.The change
Prefer
write.data.path, thenwrite.folder-storage.path, and fall back to the previous<location>/dataheuristic only when neither is set. That keeps the S3 Tables workaround intact, since it exists precisely for a catalog that does not advertise a data path.DefaultLocationGenerator::newreads the same two properties, but its fallback lacks the S3 Tables correction, so the choice is made explicitly here rather than delegated to the library.Also logs the resolved location at
debug, because a wrong data path otherwise only manifests as an opaque catalog error at commit time.Testing
No new automated test. The existing
test/icebergPolaris setup exercises only the fallback path — Polaris does not setwrite.data.path, so those workflows cover the unchanged branch and should be unaffected. Verifying the new branch needs a catalog that advertises a data path, which the harness has no way to stand up today. Confirmed manually against a Unity Catalog managed table.Release notes
This release will fix Iceberg sinks failing to commit against catalogs that manage their own data-file layout, such as Databricks Unity Catalog.
🤖 Generated with Claude Code