acoustic-carpenter-78188
03/12/2026, 11:27 PM/inputs/data path, and using user code the file can be renamed to /inputs/data.csv or something similar, if needed.
But the key issue(s)/use case(s) is this:
• We have a lot of users using Flyte, and bringing with them a great variety of user code. Highly technical users are comfortable changing the user code to rename file names for example, but the rest of the users get stuck and they find that their code fails when it runs in Flyte (namely, the user code expects .csv but flytecopilot writes the file without .csv)
• So Flyte uses blob storage. But in parallel, all the data that users work with is living in an NFS file system. Namely, all their files in the NFS are typical files (data.csv, etc. - files with extensions). Then, all of their user code expects paths more-or-less like /inputs/data.csv.
• Even though in Python, something like pandas.read_csv(path) is easily interchangeable with path=/inputs/data vs. path=/inputs/data.csv, many of our users write "SAS" code. SAS is a weird language where SAS datasets must have a particular name, like /inputs/data.sas7bdat, and it fails to process a file like /inputs/data. So unfortunately, a lot of the SAS scripts out-of-the-box will fail, but with a copilot file extensions fix, it does work!
What changes were proposed in this pull request?
[flyteidl]
Add a new file_extension string field to the BlobType protobuf message, allowing FlyteFile to optionally specify a file extension (e.g. "csv") that flytecopilot appends when writing blobs during the download phase (e.g. "data.csv"). When empty (the default), behavior is unchanged.
enable_legacy_filename bool field to the BlobType protobuf message, allowing FlyteFile to optionally specify whether to preserve backward compatibility for tasks that read from the extensionless path.BlobType.format (which can be inferred from the output filename e.g. "data.csv" -> format: "csv"), the new fields BlobType.file_extension, BlobType.enable_legacy_filename could not be inferred from the output filename (does "data.csv" match to file_extension: "csv"?). Ultimately, this seems like it is introducing a minor inconsistency, but acceptable given the benefits. (It also seems like this is all hypothetical - copilot upload does not actually infer the format from the filename, so this concern may be somewhat moot?)
Here are the other approaches I considered:
1. New flyte-copilot CLI flags --file_extension_config ENUM=(disabled, enabled, legacy)
file_extension_config = disabled (by default) - Same behavior as today (data: FlyteFile[csv] is written to outputs/data)
file_extension_config = enabled - New behavior (data: FlyteFile[csv] is written to outputs/data.csv)
file_extension_config = legacy - New behavior but backwards compatible, (data: FlyteFile[csv] is written to outputs/data and outputs/data.csv)
Cons:
• The download behavior is granular at the file level, but the CLI flag is granular at the task level (more or less). This makes the configuration less flexible, and begins to somewhat overload the configurability of copilot at the CLI level.
2. No changes, user code should be modified to read from the existing path e.g. data and add the extension itself
Cons:
• Migrating large projects to Flyte becomes burdensome, when needing to add another extra step like this here - user code needs to be modified to handle adjusting the file extensions on inputs.
How was this patch tested?
# Container task python code
def t1(datasetA: FlyteFile[TypeVar('csv')], datasetB=Annotated[FlyteFile[TypeVar('csv')], FileDownloadConfig(file_extension="csv", enable_legacy_filename=True)]): …
# flyte-copilot logs
{"json":{},"level":"debug","msg":"inputInterface: [variables:{key:\"datasetA\" value:{type:{blob:{format:\"csv\"}} description:\"datasetA\"}} variables:{key:\"datasetB\" value:{type:{blob:{format:\"csv\" file_extension:\"csv\" enable_legacy_filename:true}} description:\"datasetB\"}}]","ts":"2026-03-10T23:20:55Z"}
{"json":{},"level":"debug","msg":"varFilenames: map[datasetA:[datasetA[] datasetB:[datasetB.csv datasetB]]","ts":"2026-03-10T23:20:55Z"}
...
{"json":{},"level":"info","msg":"Successfully copied [4119] bytes remote data from [<s3://rliucp108882-flyte-data//a0c46ac7-eea3-427d-91c1-a3c6b4a27e83/datasetB>] to local [/execution-vol/flows/workflow/inputs/datasetB]","ts":"2026-03-10T23:20:55Z"}
{"json":{},"level":"info","msg":"Successfully copied [4119] bytes remote data from [<s3://rliucp108882-flyte-data//a0c46ac7-eea3-427d-91c1-a3c6b4a27e83/datasetB>] to local [/execution-vol/flows/workflow/inputs/datasetB.csv]","ts":"2026-03-10T23:20:55Z"}
{"json":{},"level":"info","msg":"Successfully copied [3904] bytes remote data from [<s3://rliucp108882-flyte-data//af859c71-811d-4c26-9845-b3fd8830ab6b/datasetA>] to local [/execution-vol/flows/workflow/inputs/datasetA]","ts":"2026-03-10T23:20:55Z"}
Labels
Please add one or more of the following labels to categorize your PR:
• added: For new features.
• changed: For changes in existing functionality.
• deprecated: For soon-to-be-removed features.
• removed: For features being removed.
• fixed: For any bug fixed.
• security: In case of vulnerabilities
This is important to improve the readability of release notes.
Setup process
Screenshots
Check all the applicable boxes
• I updated the documentation accordingly.
• All new and existing tests passed.
• All commits are signed-off.
Related PRs
Docs link
flyteorg/flyteacoustic-carpenter-78188
03/12/2026, 11:27 PM