Bulk Import - Manifest Files
A manifest is an optional CSV or TSV file that tells Bulk Import exactly where each source file belongs. Each row names one source file and gives the subject, session, and acquisition labels for it, along with any other container or file metadata to set.
Manifests are intended for source data whose paths and file contents do not carry enough information to place files in the Flywheel hierarchy, such as vendor-supplied, de-identified, or inconsistently organized data. Values in the manifest take precedence over values that Flywheel derives from file paths, DICOM headers, and metadata sidecar files.
Prefer rule sets when the source data already has the information
When the labels and metadata can be derived from file paths or DICOM headers, use import rules and rule sets instead of a manifest. Rules describe many files with a few patterns, so they scale and perform better on large datasets, and they are easier to maintain and reuse across imports. Use a manifest for the information that rules cannot derive, and let rules handle the rest.
Requirements
Manifest files require Flywheel 22.5.0 or later. The New CLI (flyw) updates itself to match the version of the Flywheel site it connects to.
Where the Manifest Goes
The manifest is not placed in the source data location. It is a local file on the computer that runs the New CLI (flyw), and it is supplied when the import starts. The CLI uploads the manifest to Flywheel and associates it with the import job, and Flywheel keeps the uploaded copy with the import for traceability. Flywheel then reads the source files from the source location, as it does for any import, and looks up each file in the manifest.
The import command names both locations:
Do not store the manifest with the source files
Flywheel does not look for a manifest inside the source location. A manifest stored alongside the source files is treated as an ordinary file, and it is imported like any other file if an import rule matches it.
Manifests stored in cloud storage
Flywheel cannot read a manifest directly from cloud storage, including from an External Storage. If the manifest is kept in a bucket, download it to the computer that runs the CLI first, and pass the local copy to --manifest.
See How to Run a Bulk Import (CLI) for the full command.
How Flywheel Applies the Manifest
A manifest supplies metadata values. It does not decide which files are imported or the hierarchy level that each file is imported to. Import rules still make those decisions:
- Flywheel scans the source location and matches each file against the import rules, either from the selected rule set or the default rules. A rule matches a file when the file passes the rule's
includeandexcludefilters. Files that no rule matches are skipped, even if the manifest lists them. - Flywheel derives labels and metadata for the file from its path, its DICOM headers, and any metadata sidecar file, according to the matching rule.
- Flywheel looks up the file's path in the manifest's
src_pathcolumn. If a row matches, every non-empty value in that row replaces the derived value for that field. - Flywheel checks that the file has every label that its rule's hierarchy level requires. For example, a rule at the
acquisitionlevel requires subject, session, and acquisition labels. A file that is still missing a label fails, or is skipped if the import uses--missing-meta skip.
The following behaviors follow from this process:
- Files not listed in the manifest are imported with their derived values, as if no manifest were supplied.
- Rows for files that are not in the source location are ignored. If a row's
src_pathdoes not match any file that Flywheel finds during the scan, the row has no effect, and Flywheel does not report it. - Empty cells are ignored, so the derived value for that field is kept.
- Duplicate
src_pathrows are not rejected. Flywheel uses the first matching row and ignores the rest. - Grouped files use only the first matching row. When Flywheel groups several files into one archive, such as the files of a DICOM series, it applies a single manifest row to the whole group: the row for the first file in the group, in scan order, that the manifest lists. Rows for the group's other files are ignored, so a manifest needs only one row per DICOM series. See Example 2.
Matching src_path to Source Files
Flywheel matches each src_path value to a source file by exact comparison:
- The path is relative to the root of the source location. For an External Storage, this is the storage location, including any path prefix configured on the storage. For a local import, this is the folder passed to
--storage. - Use forward slashes (
/) between folders, and do not start the path with/. - Matching is case-sensitive.
- Wildcards and patterns are not supported. Each file needs its own row.
For example, if the storage location is s3://example-bucket/vendor-delivery-03, the file s3://example-bucket/vendor-delivery-03/scans/1001_t1.nii has the src_path value scans/1001_t1.nii.
Checking the path format
The src_path column of the import audit report uses the same path format. To list source paths before building a manifest, run the import with --dry-run, which processes files without transferring them, and review its audit report.
File Format
| Requirement | Details |
|---|---|
| Format | CSV (comma-separated values) or TSV (tab-separated values). The New CLI treats a file with the .tsv extension as TSV, and any other file as CSV. |
| Encoding | UTF-8 text |
| Header row | The first line lists the column names. Each following line describes one source file. |
| Required column | src_path is the only required column. All other columns are optional. |
| Other columns | At least one supported column in addition to src_path. Columns can appear in any order. |
| Unsupported columns | Not allowed. Flywheel rejects a manifest that contains any column it does not recognize. |
| Multiple values | Tag and classification cells accept several values separated by commas. In a CSV file, wrap such a cell in double quotes, for example "baseline,qc-passed". |
Group and project are set by the import, not the manifest
A manifest cannot change the destination group or project. The destination project is the project given when the import starts, and Flywheel rejects a manifest that contains group or project columns.
Supported Columns
The manifest uses the same field names as import mapping rules, except that group and project fields are not allowed. Most fields also accept a shorter name.
Every column except src_path is optional, so a manifest can set only the container labels and leave everything else, including file names, to be derived as usual.
Subject Columns
| Column | Also accepted as | Value |
|---|---|---|
subject.label | subject | Subject label. Values longer than 64 characters are truncated. |
subject.firstname | Text | |
subject.lastname | Text | |
subject.sex | male, female, other, or unknown. M, F, and O are also accepted. | |
subject.type | human, animal, or phantom | |
subject.species | Text | |
subject.strain | Text | |
subject.tags | One or more tags, separated by commas | |
subject.info.<key> | Custom information value. See Custom information values. |
Session Columns
| Column | Also accepted as | Value |
|---|---|---|
session.label | session | Session label. Values longer than 64 characters are truncated. |
session.timestamp | session.time, session.ts | Date and time, for example 2026-01-14T09:32:00Z |
session.timezone | Time zone name, for example America/Chicago | |
session.age | Subject age at the time of the session, in seconds, as a whole number | |
session.weight | Subject weight, as a number | |
session.operator | Text | |
session.tags | One or more tags, separated by commas | |
session.info.<key> | Custom information value |
Acquisition Columns
| Column | Also accepted as | Value |
|---|---|---|
acquisition.label | acquisition | Acquisition label. Values longer than 128 characters are truncated. |
acquisition.timestamp | acquisition.time, acquisition.ts, timestamp | Date and time, for example 2026-01-14T09:45:00Z |
acquisition.timezone | Time zone name | |
acquisition.tags | One or more tags, separated by commas | |
acquisition.info.<key> | Custom information value |
File Columns
| Column | Also accepted as | Value |
|---|---|---|
file.name | file | Name to give the file in Flywheel. See File names. |
file.type | File type, for example nifti | |
file.modality | Modality, for example MR. Required in the same row when setting a classification. See Classification values. | |
file.classification.<key> | classification.<key> | One or more classification values for the key, for example file.classification.Intent set to Structural |
file.tags | One or more tags, separated by commas | |
file.info.<key> | info.<key> | Custom information value |
Custom Information Values
Columns that end in .info.<key> set a custom information field, where <key> is the field name. For example, a file.info.scanner column sets the scanner field in the file's custom information.
Flywheel stores numbers as numbers, true and false as Boolean values, and valid JavaScript Object Notation (JSON) as structured data. Any other value is stored as text.
Classification Values
Flywheel validates classification values against the classification schema for the file's modality. When a row sets a file.classification.<key> column, also set file.modality in the same row to a modality that is configured on your site, such as MR.
Without a recognized modality, only the Custom classification key is accepted, and a file with any other classification key fails with the error Unknown modalities can only use the custom attribute. For more information, see Data Classification.
File Names
The file.name column is optional. When a row does not set it, Flywheel names the file as it would without a manifest:
- A file imported on its own keeps its source file name.
- A DICOM series archive is named after the acquisition label that the import rules derive for it. With the built-in DICOM Only rule set, that label comes from the DICOM headers, as described in Bulk Import - Default Behavior. Other rule sets can derive it from the file path or from custom mappings.
Flywheel names a DICOM series archive before it applies the manifest. If the manifest changes a series' acquisition label but not its file.name, the archive moves to the manifest's acquisition but keeps the name that the rules derived. To name the archive after the manifest's label, set file.name to the same value. Flywheel adds the .dicom.zip extension if the value does not already end with it.
Template
A manifest always has a src_path column followed by the columns to set. Choose only the columns your data needs:
The following starter template includes commonly used columns. Leave a cell empty to keep the value that Flywheel derives for that field, and delete any column you do not need.
Examples
Example 1: Files with No Hierarchy in Their Paths
A vendor delivers NIfTI files in a single flat folder. File names identify the subject, but no folder structure describes subjects, sessions, or acquisitions, so path-based mapping cannot place the files.
Source location, registered as an External Storage at s3://example-bucket/vendor-delivery-03:
Manifest file, saved as vendor-delivery-03.csv on the computer running the CLI:
Because the files sit at the root of the source location, the default rules would import them as project attachments. A rule file that imports .nii files at the acquisition level, saved as nifti-acquisitions.yaml, lets the manifest labels take effect:
Import command:
Result in Flywheel:
Example 2: DICOM Files with Labels, Classification, and Custom Information
A local folder contains de-identified DICOM files from two series, whose headers no longer carry usable patient and study identifiers. The manifest sets the container labels, names each series archive, classifies each series, and adds custom information to the subject and to each file.
Source folder on the local computer. Files whose names start with 1- belong to one series, and files whose names start with 2- belong to another:
Manifest file, saved as study-export.csv outside the source folder:
The columns work as follows:
subject,session, andacquisitionset the container labels.file.namenames each series archive after its new acquisition label. Flywheel adds the.dicom.zipextension. Without this column, each archive would keep the name that the DICOM Only rule set derives from its headers. See File names.file.modalityand thefile.classification.*columns classify each series. The modality is required for the classification to be accepted. See Classification values.subject.info.cohortsets thecohortfield in the subject's custom information.file.info.source_sitesets thesource_sitefield in each archive's custom information.
Flywheel imports each series as one archive and uses only the first row it finds for that series, so the rows for 1-02.dcm, 1-03.dcm, 2-02.dcm, and 2-03.dcm above are never used. The manifest can therefore list just one file from each series and produce the same result. For large deliveries, this makes the manifest much smaller and easier to prepare:
Import command, using the built-in DICOM Only rule set (ID 000000698487153c61668b43):
Result in Flywheel:
Manifest Uploads and Traceability
When an import starts, the CLI uploads its manifest to Flywheel, and Flywheel associates that copy with the import job. The association is with the import, not with the user who started it:
- Rerunning the import with Rerun Job uses the same manifest, whoever reruns it, so nobody needs to find or supply the original file again.
- Editing the manifest file afterward does not change the copy that the import used. A new import with the edited file uploads and records the new version.
Validation Errors
Flywheel checks the manifest's format and header row when the manifest is uploaded, before the import starts. It does not check whether the listed files exist in the source location. If a check fails, the import does not start, and the CLI's error output contains one of the following messages:
| Error message | Cause |
|---|---|
Manifest file not found: <path> | The local path given to --manifest does not exist. |
Manifest is empty | The file has no content. |
Manifest is not valid UTF-8 text | The file uses a different text encoding. Save it as UTF-8. |
Manifest missing required column: src_path | The header row has no src_path column. |
Manifest must contain at least one metadata column | The header row has only a src_path column. |
Manifest has unrecognized column(s): <columns> | The header row contains unsupported column names, including group or project. |
Problems with individual rows appear as failed files in the import audit report, with one of the following messages in the reason column:
| Error message | Cause |
|---|---|
Unknown modalities can only use the custom attribute | The row sets a classification without a recognized file.modality. See Classification values. |
Incomplete upload metadata, missing fields: <fields> | The file is missing a label that its rule's hierarchy level requires, and neither the manifest nor the file's path or headers supply it. |
Limitations
- The manifest cannot set the destination group or project.
src_pathvalues must match source paths exactly. Wildcards and patterns are not supported.- Import schedules do not accept a manifest.
- Starting an import with a manifest from the web app is not currently available. Use the New CLI (
flyw). An import that already used a manifest can still be rerun from the web app with Rerun Job.