Repository navigation
BUG: C07: Preflight/execute or Direct/Scanline disagree in 53 filters #1867
Description
Summary
In some filters, preflight and execute do not apply the same rules to the same inputs. Preflight accepts an input (or creates an output) that execute handles in a different way. In other filters, the in-core (Direct) and out-of-core (Scanline) algorithms give different results for the same input. Both forms can crash, write wrong data with no error, or pass preflight and then fail late in execute.
Open findings as of develop 419f9db (2026-10-21): 13 CRASH, 16 WRONG_DATA, 44 MINOR (73 findings) in 53 filters. Each finding is a candidate: it was found and re-checked by reading code, not by running it.
Mechanism
This class has two sub-patterns.
1. Preflight and execute disagree. Preflight checks only some modes, reads only the first input of a list, uses other names or other arithmetic than execute, or creates outputs that execute does not write. Execute trusts that preflight checked the input. Example from AlignSectionsListFilter: the tuple-count check for the Shifts Array is inside if(!pUseFileValue). pUseFileValue is the Input Array Type choice index, so the check runs only for Relative (index 0).
AlignSectionsListFilter.cpp#L119-L131
if(!pUseFileValue)
{
const auto* shiftsArray = dataStructure.getDataAs<IDataArray>(pShiftsArrayPathValue);
if(shiftsArray == nullptr)
{
return MakePreflightErrorResult(-8942, "Shifts array is not valid.");
}
if(shiftsArray->getNumberOfTuples() != imageGeom.getNumZCells())
{
return MakePreflightErrorResult(-8943, fmt::format("The size of shifts array ({}) does not align with Z Dimension of geometry ({})", shiftsArray->getNumberOfTuples(), imageGeom.getNumZCells()));
}
}The Cumulative branch in execute has the comment // Size validated in preflight and writes one shift per Shifts Array tuple (AlignSectionsList.cpp#L55-L64). A Shifts Array with 200 tuples on an Image Geometry with Z = 100 writes past the end of the shift vectors.
Fixed form (PR #1839, commit 2eb6b87): ReadGrainMapper3DFilter created IPF color arrays in preflight that execute then requested in a different way. The fix adds one helper, GrainMapper3DUtilities::IsIpfColorDataset, and uses the same condition in preflight (ReadGrainMapper3DFilter.cpp#L189) and in execute (ReadGrainMapper3D.cpp#L380-L384):
const auto dataTypeIter = nameToDataTypeMap.find(dataSetName);
if(!IsIpfColorDataset(dataSetName) || dataTypeIter == nameToDataTypeMap.end() || dataTypeIter->second != DataType::float32)
{
continue;
}2. Direct and Scanline disagree. A filter that dispatches between an in-core (Direct) and an out-of-core (Scanline) algorithm has two copies of the same logic. When only one copy gets a guard or a correct initial value, the result depends on the storage. Example: the Direct path of ComputeArrayHistogramByFeatureFilter starts the per-feature maximum at std::numeric_limits<T>::min(), which is a small positive value for float (HistogramUtilities.hpp#L393-L394). A feature with only negative values gets a wrong maximum in-core, while Scanline gives the correct value.
Rule
- Preflight and execute must make the same decision from the same inputs. Put the shared decision (crop index, output name, list of arrays to process, enabled outputs, valid modes) in one helper and call it from both. Do not copy the logic.
- Checks belong in preflight unless they need array values. Check every mode, every geometry type and every item of a list (every scan, every input geometry), not only the first one.
- Every output that preflight creates must be written by execute, or preflight must not create it. Preflight must give the output the same shape that execute gives it.
- Direct and Scanline must give the same output for the same input. A guard or a fix in one path goes in the other path too, preferably in a shared helper.
- Remove execute-time checks that a new preflight check makes unreachable (no duplicate checks).
- Decision needed for the findings marked "Decision needed" in the checklist. Choose the option in the PR and write the reason.
How to fix
- Read the checklist line and the linked code. Find where preflight and execute (or Direct and Scanline) diverge.
- Move the shared decision into one function that both sides call. Examples: use geometry accessors such as
INodeGeometry0D::getVertexAttributeMatrixDataPath()instead of fixed names, compute crop indices with the float64 preflight helper (ImageGeometryCrop.cpp) in execute, and name outputs withStringUtilities::GenerateIndexStringin both places. - When a check needs only metadata (dimensions, names, parameter values, file headers), add it to
preflightImpland return a filter-specific error. - When an input is a list (scans, input geometries, files), check every item in preflight.
- For Direct/Scanline findings, use the same initial values (
std::numeric_limits<T>::lowest()for a running maximum), the same accumulator type, and the same overflow guards in both paths. - New filter error codes must be more negative than -10000 and stay in the filter's existing range (first code -47500 means all codes -47500..-47599). Check that each code is unique with
git grep -nE -- "-NNNN([^0-9]|$)"(do not use\b;git grep -Eignores it). Check open PR branches too. - Remove the old execute-time check when the new preflight check makes it unreachable.
How to test
- Write the test first. It must fail on develop.
- Preflight/execute findings: build the input from the checklist line (for example Input Array Type = Cumulative with 200 Shifts Array tuples on an Image Geometry with Z = 100). Require a preflight error with the new code. Where the defect is a crash in execute, the test must reach preflight only; do not run execute on develop inside the test if it would crash the test process.
- Output mismatch findings: run preflight and execute, and require that the output that preflight declares (name, tuple shape, component shape) is the output that execute writes.
- Direct/Scanline findings: run the same input on both paths with the existing algorithm-selection test scope. Loop over
UnitTest::SelectAlgorithmTestScenariosForInMemoryStores()and create aUnitTest::AlgorithmTestScopeper scenario (seeComputeArrayStatisticsTest.cpp). Require the same values on both paths. - Compare output values with an independent expected result (oracle), for example a hand-computed value for a small input. Do not use the code's own output as the expected value.
- If a finding cannot be reproduced, write that in the PR and on this issue, with the reason. Do not force a fix.
Conventions
- One PR for the whole class. One commit per filter.
- Commit prefix
BUG:. Add aSigned-off-byline. No AI attribution. - Every fix starts with a unit test that fails on develop.
- Value checks need an independent expected result (oracle), not the code's own output.
- Run
ctestserially. Never use-j(tests depend on each other). - Format with clang-format 19.1.1 and the repository
.clang-format. - Do NOT add per-filter documentation sentences about input requirements. The generated parameter table documents them.
- If a fix touches a filter that has a V&V report (
src/Plugins/<Plugin>/vv/<Filter>.md), update every file of that filter's V&V package (report, deviations, provenance, test tables). V&V documents reference DREAM3D 6.5.171 only. - Rebase on develop. Never merge develop into the branch.
Checklist
- CRASH · AlignSectionsListFilter · AlignSectionsListFilter.cpp:119 — The shifts tuple-count check (-8943) runs only for Input Array Type = Relative; with Cumulative and a Shifts Array of 200 tuples on an Image Geometry with Z = 100, execute writes past the end of the shift vectors.
AlignSectionsListFilter#1 - CRASH · AppendImageGeometryFilter · AppendImageGeometry.cpp:129 — Preflight skips input arrays whose type or components differ from the destination (warnings -8208/-8209/-8211), but execute still collects them; a failed cast gives a null pointer that is dereferenced.
AppendImageGeometryFilter#1 - CRASH · ApplyTransformationToGeometryFilter · GeometryTransformation.cpp:455 — For Linear interpolation preflight drops String, Bool and NeighborList arrays, but execute loops over every Cell Data child;
IsOutOfCore(*ptr)dereferences the null pointer.ApplyTransformationToGeometryFilter#2 - CRASH · ApplyTransformationToGeometryFilter · ApplyTransformationToGeometryFilter.cpp:105 — Selected Geometry accepts every geometry type, including RectGrid, but execute handles only Image and node geometries; a RectGrid with Translate To Origin on dereferences a null node geometry.
ApplyTransformationToGeometryFilter#5 - CRASH · CombineStlFilesFilter · CombineStlFiles.cpp:119 — Preflight sizes the Feature Attribute Matrix from the STL files it finds; execute lists the directory again and writes one entry per file with no bound check, so a file added by an earlier filter in the pipeline gives an out-of-bounds write.
CombineStlFilesFilter#5 - CRASH · ComputeTriangleAreasFilter · ComputeTriangleAreasFilter.cpp:133 — Preflight uses
getNumberOfFaces(), which returns 0 when the shared Face List is missing; execute callsgetFaces()->getDataStoreRef()with no null check.ComputeTriangleAreasFilter#1 - CRASH · ComputeVertexToTriangleDistancesFilter · ComputeVertexToTriangleDistances.cpp:449 — The parallel algorithm accesses DataStores from many threads with no
requireArraysInMemory; with out-of-core stores this can corrupt data or crash.ComputeVertexToTriangleDistancesFilter#4 - CRASH · FeatureFaceCurvatureFilter · CalculateTriangleGroupCurvatures.cpp:182 — Execute decides what to compute from non-null output pointers, not from the Compute ... options; a disabled output path that names an existing 1-component array is written out of bounds.
FeatureFaceCurvatureFilter#4 - CRASH · PointSampleEdgeGeometryFilter · PointSampleEdgeGeometry.cpp:152 — Preflight creates the vertex Attribute Matrix with the user's name, but execute builds the path with the fixed name
Vertex Data; any other name gives a null pointer that is dereferenced.PointSampleEdgeGeometryFilter#1 - CRASH · ReadChannel5DataFilter · ReadChannel5Data.cpp:276 — With Convert Data Arrays to be more compatible with DREAM3D on, preflight does not require the Euler and Phase fields; a .cpr file without them makes execute dereference null field pointers.
ReadChannel5DataFilter#2 - CRASH · ReadH5EspritDataFilter · ReadH5EspritData.cpp:25 — Preflight reads only the first scan; execute uses the first scan's X*Y for every scan, so a second scan with fewer columns or rows gives a heap out-of-bounds read.
ReadH5EspritDataFilter#1 - CRASH · ReadH5OimDataFilter · ReadH5OimDataFilter.cpp:131 — Preflight sizes the geometry and the Ensemble Attribute Matrix from the first scan only; a later scan with fewer rows or columns, or more phases, gives out-of-bounds reads and writes in execute.
ReadH5OimDataFilter#2 - CRASH · ReadH5OimDataFilter · ReadH5OimData.cpp:103 — With Import Pattern Data on, execute copies X*Y patterns without checking the size of the Pattern dataset; a short dataset gives an out-of-bounds read, and a missing dataset in a later scan fails only at execute (-34880).
ReadH5OimDataFilter#4 - WRONG_DATA · ApplyTransformationToGeometryFilter · GeometryTransformation.cpp:227 — For an Image Geometry with Transformation Type = No Transform, preflight replaces the Cell Data with new zero-filled arrays, but execute returns early; the Cell Data becomes zeros.
ApplyTransformationToGeometryFilter#1 - WRONG_DATA · ArrayCalculatorFilter · ArrayCalculator.cpp:1224 — Execute parses the expression again after preflight created the output; if the output name equals an operand name, the operand resolves to the new zero-filled output.
ArrayCalculatorFilter#3 - WRONG_DATA · ComputeArrayHistogramByFeatureFilter · HistogramUtilities.hpp:393 — The Direct path starts the maximum at
numeric_limits<T>::min()(a positive value for float); a feature with only negative values gets a wrong maximum, while Scanline is correct.ComputeArrayHistogramByFeatureFilter#2 - WRONG_DATA · ComputeArrayHistogramByFeatureFilter · ComputeArrayHistogramByFeature.cpp:231 — The Direct path computes max + 1 with none of the overflow guards (-23808/-23810) that Scanline has; uint8 value 255 wraps to 0, so bins are wrong in-core while out-of-core fails cleanly.
ComputeArrayHistogramByFeatureFilter#3 - WRONG_DATA · ComputeArrayStatisticsFilter · ComputeArrayStatistics.cpp:384 — The Direct per-feature path sums in the input type T, while Scanline uses float; uint8 {200, 200} sums to 144, so Summation, Mean, Std Dev and Standardized are wrong in-core.
ComputeArrayStatisticsFilter#1 - WRONG_DATA · ComputeMomentInvariants2DFilter · ComputeMomentInvariants2D.cpp:284 — The Direct path uses
returninstead ofcontinuewhen a feature has zDim != 1, which ends the whole parallel sub-range; later features stay 0 in-core but not in Scanline. (related: BUG: Skip only unused features in 2D moment calculations #1775)ComputeMomentInvariants2DFilter#1 - WRONG_DATA · ComputeTriangleGeomVolumesFilter · ComputeTriangleGeomVolumes.cpp:43 — Execute resizes the Face Feature Attribute Matrix to the largest Face Label + 1 with no check; when that is smaller than the Attribute Matrix, the matrix and every sibling array are truncated.
ComputeTriangleGeomVolumesFilter#1 - WRONG_DATA · NearestPointFuseRegularGridsFilter · NearestPointFuseRegularGridsFilter.cpp:123 — Preflight creates an output StringArray for each sampling StringArray, but the algorithm skips non-numeric arrays; the outputs stay empty and execute succeeds.
NearestPointFuseRegularGridsFilter#2 - WRONG_DATA · PartitionGeometryFilter · PartitionGeometryFilter.cpp:360 — The partitioning-mode checks (counts > 0, Cell Length >= 0, min <= max) run only for Image Geometry; RectGrid and node geometries with a count of 0 or a negative length make a degenerate grid with no error.
PartitionGeometryFilter#3 - WRONG_DATA · ReadBinaryCTNorthstarFilter · ReadBinaryCTNorthstarFilter.cpp:491 — Preflight checks that the data files exist but does not compare the sum of their slice counts with Voxels Z; too few slices leave Density slices filled with the 0xABCDEF sentinel and execute succeeds.
ReadBinaryCTNorthstarFilter#3 - WRONG_DATA · ReadCSVFileFilter · ReadCSVFileFilter.cpp:379 — The tuple-count vs line-count check is skipped when Use Existing Data Group or Attribute Matrix is on; a 10-tuple Attribute Matrix and a 5-line CSV leave the last tuples 0 with no error.
ReadCSVFileFilter#2 - WRONG_DATA · ReadCSVFileFilter · ReadCSVFileFilter.cpp:259 — The header cache is refreshed only when the file or the header line changes; a new delimiter keeps the old header names, so arrays get wrong names or preflight fails -109.
ReadCSVFileFilter#4 - WRONG_DATA · ReadGrainMapper3DFilter · ReadGrainMapper3D.cpp:443 — Preflight creates arrays for datasets of every mapped type, but execute fills only float32, int32 and uint8; datasets of other types (for example uint32 GrainId) stay 0 and execute succeeds.
ReadGrainMapper3DFilter#1 - WRONG_DATA · ReadNIfTIFileFilter · ReadNIfTIFile.cpp:109 — Execute converts the crop bounds to indices in float32 (
ImageGeom::getIndex), while preflight uses float64; the index can differ by one, so rows are copied from the wrong voxels with no error.ReadNIfTIFileFilter#2 - WRONG_DATA · ReadStlFileFilter · ReadStlFile.cpp:42 — Preflight treats a header triangle count of 0 as 1 (the code says this is common), but execute uses 0 and reads no triangles; every triangle is dropped with no error.
ReadStlFileFilter#1 - WRONG_DATA · ReadZeissTxmFileFilter · ReadZeissTxmFile.cpp:152 — Execute converts the crop bounds to indices in float32 (
ImageGeom::getIndex), while preflight uses float64; the index can differ by one, so rows are copied from the wrong voxels with no error.ReadZeissTxmFileFilter#2 - MINOR · AppendImageGeometryFilter · AppendImageGeometry.cpp:122 — When appending in place and an input lacks a destination array, preflight never parses Default Value; an invalid value fails at execute after the destination was already resized.
AppendImageGeometryFilter#5 - MINOR · AppendImageGeometryFilter · AppendImageGeometry.cpp:108 — Preflight does not reject the destination geometry in Input Image Geometries; execute resizes the destination and then fails (-2034), leaving it resized.
AppendImageGeometryFilter#6 - MINOR · AppendImageGeometryFilter · AppendImageGeometryFilter.cpp:333 — When appending in place, preflight has no action that resizes the destination, so downstream filters see the old dimensions in preflight while execute resizes.
AppendImageGeometryFilter#8 - MINOR · ArrayCalculatorFilter · ArrayCalculatorFilter.cpp:101 — Preflight replaces any 1-tuple result shape with the Attribute Matrix shape, also for a 1-tuple array result (not a scalar); execute then fails (-6030).
ArrayCalculatorFilter#5 - MINOR · ArrayCalculatorFilter · ArrayCalculator.cpp:582 — A
[T, C]extraction after a parenthesized sub-expression is not range-checked in preflight; an out-of-range index fails only at execute.ArrayCalculatorFilter#6 - MINOR · ArrayCalculatorFilter · ArrayCalculator.cpp:1692 — The tuple-count comparison is skipped when the first array has 0 tuples, so
Z + Apasses preflight and fails at execute (-6030), whileA + Zfails in preflight (-4016).ArrayCalculatorFilter#7 - MINOR · BinaryOpeningByReconstructionImageFilter · BinaryOpeningByReconstructionImageFilter.cpp:106 — Preflight compares Foreground and Background as float64 before truncation; 1.5 and 1.0 pass preflight for integer input, then execute fails with a misleading non-binary error (-8002).
BinaryOpeningByReconstructionImageFilter#1 - MINOR · ComputeArrayStatisticsFilter · ComputeArrayStatistics.cpp:1019 — For empty features the Direct path writes
numeric_limits<T>::min()as the Maximum, while Scanline writeslowest(); only the sentinel differs.ComputeArrayStatisticsFilter#6 - MINOR · ComputeBoundingBoxStatsFilter · ComputeBoundingBoxStatsScanline.cpp:655 — Scanline sorts float data that contains NaN with
operator<, which is not a strict weak ordering; Median and Number of Unique Values can differ from the Direct path.ComputeBoundingBoxStatsFilter#9 - MINOR · ComputeFeatureClusteringFilter · ComputeFeatureClusteringFilter.cpp:144 — Number of Bins for RDF has no >= 1 check; 0 passes preflight and fails at execute (-263), and -1 gives an unclear overflow error.
ComputeFeatureClusteringFilter#4 - MINOR · ComputeGBCDFilter · ComputeGBCDFilter.cpp:130 — GBCD Spacing (Degrees) has no range check; 0, negative or 200 fail later with generic array-creation errors (-270/-263).
ComputeGBCDFilter#5 - MINOR · ComputeGBCDPoleFigureFilter · ComputeGBCDPoleFigureFilter.cpp:112 — Preflight checks only the upper bound of Phase of Interest; 0, or a phase not in Crystal Structures, fails only at execute (-34643).
ComputeGBCDPoleFigureFilter#3 - MINOR · ComputeNeighborListStatisticsFilter · ComputeNeighborListStatistics.cpp:185 — A NeighborList with 0 tuples fails only at execute (-6803); preflight does not check it.
ComputeNeighborListStatisticsFilter#2 - MINOR · ConcatenateDataArraysFilter · DataArrayUtilities.hpp:908 —
CopyDatareturns -2032 when the destination offset equals the destination size, even when there is nothing to copy; a trailing empty input fails at execute.ConcatenateDataArraysFilter#1 - MINOR · CreateColorMapFilter · CreateColorMapParameter.cpp:67 —
CreateColorMapParameter::validateaccepts any value and preflight does not extract the control points; an indexed or misspelled preset fails only at execute (-36782/-36783).CreateColorMapFilter#2 - MINOR · CreateDataArrayFilter · CreateDataArrayFilter.cpp:119 — Total Number of Components = 0 passes preflight; array creation rejects it only at execute (-263).
CreateDataArrayFilter#2 - MINOR · CreateEnsembleInfoFilter · CreateEnsembleInfoFilter.cpp:83 — Preflight does not validate the ensemble rows (empty name, unknown phase type or crystal structure); they fail only at execute (-10006/-10007/-10008).
CreateEnsembleInfoFilter#1 - MINOR · CreateGeometryFilter · CreateGeometry.cpp:49 —
RectGridGeom::setBoundsrejects non-increasing bounds (-4007) before the algorithm, so the warning path (-8342/-8343) is unreachable and uses>instead of>=.CreateGeometryFilter#3 - MINOR · CropImageGeometryFilter · ImageGeometryCrop.cpp:226 — With physical bounds, a Min Coordinate equal to the bounding-box maximum passes preflight, and the later xMax = xMin + 1 clamp is not re-checked; execute rejects it (-950).
CropImageGeometryFilter#6 - MINOR · EbsdToH5EbsdFilter · EbsdToH5Ebsd.cpp:155 — Preflight lower-cases the file extension, but execute compares it case-sensitively;
.ANGor.Ctfpasses preflight and fails at execute (-99512).EbsdToH5EbsdFilter#1 - MINOR · FeatureFaceCurvatureFilter · FeatureFaceCurvatureFilter.cpp:96 — Principal Curvature 1/2 are hidden when Compute Principal Direction Vectors is off, but preflight always creates them; a collision gives an error on a parameter the user cannot see.
FeatureFaceCurvatureFilter#11 - MINOR · ImportFijiMontageFilter · ImportFijiMontageFilter.cpp:351 — Color Weighting is validated only in execute (-10704), after the first tile is read; preflight only adds a note.
ImportFijiMontageFilter#2 - MINOR · MapPointCloudToRegularGridFilter · MapPointCloudToRegularGridFilter.cpp:135 — Preflight creates the Image Geometry with Grid Dimensions, but execute adds 1 per axis; downstream preflight sees other dimensions. Decision needed: keep the requested dimensions, or report the final ones in preflight.
MapPointCloudToRegularGridFilter#3 - MINOR · MedianImageFilter · BoxNeighborhoodEngine.hpp:150 — The out-of-core 2D plan counts per-worker scratch in the fixed memory target; a large radius fails at execute (-8615) out-of-core while in-core succeeds.
MedianImageFilter#1 - MINOR · MedianProjectionImageFilter · AxisProjectionEngine.hpp:1683 — The median path requires a rank-3 tuple shape (-8344), but preflight checks only the tuple count; a 1-D tuple shape with the right count fails at execute.
MedianProjectionImageFilter#1 - MINOR · MoveDataFilter · MoveDataFilter.cpp:87 — Preflight compares tuple shapes and only warns (-69250), while insert compares tuple counts; a count mismatch fails at execute as generic -6404, and a shape-only mismatch gets a misleading warning.
MoveDataFilter#2 - MINOR · NearestPointFuseRegularGridsFilter · NearestPointFuseRegularGrids.cpp:35 — The zero-spacing check for the sampling geometry (-5555) is only in execute, although preflight knows the spacing.
NearestPointFuseRegularGridsFilter#4 - MINOR · PointSampleTriangleGeometryFilter · PointSampleTriangleGeometryFilter.cpp:129 — Preflight creates the Vertex Geometry with the tuple count of the first transfer array (or 0), not Number of Sample Points; downstream preflight sees the wrong vertex count.
PointSampleTriangleGeometryFilter#4 - MINOR · ReadDeformKeyFileV12Filter · ReadDeformKeyFileV12Filter.cpp:115 — The cache key is only the file path and time stamp; after a rename of the Quad Geometry or an Attribute Matrix, cached paths are stale and preflight fails (-2022).
ReadDeformKeyFileV12Filter#3 - MINOR · ReadGrainMapper3DFilter · GrainMapper3DUtilities.cpp:30 — SpaceGroup 0 gives index SIZE_MAX and
at()throws at execute; a negative value maps to the last entry (cubic) with no error. Preflight does not check 1..230.ReadGrainMapper3DFilter#7 - MINOR · ReadH5EbsdFilter · ReadH5EbsdFilter.cpp:119 — Preflight sets Z from the selected start and end slices without comparing them with the file's Z range; an out-of-range slice fails at execute with generic -50003.
ReadH5EbsdFilter#6 - MINOR · ReadNIfTIFileFilter · ReadNIfTIFile.cpp:109 — Preflight clamps crop bounds outside the volume (-50503 warning), but execute uses
getIndex, which fails (-34740/-34741) for the same bounds.ReadNIfTIFileFilter#1 - MINOR · ReadOnScaleTableFileFilter · ReadOnScaleTableFile.cpp:428 — A repeated bounds section overwrites the preflight count; execute compares the first section and fails with a misleading 'file changed after preflight' error (-12060).
ReadOnScaleTableFileFilter#2 - MINOR · ReadOnScaleTableFileFilter · ReadOnScaleTableFile.cpp:179 — With
__cpp_lib_to_chars,from_charsrejects+1.0and hex floats; thestrtof_lfallback accepts them, so the result depends on the platform.ReadOnScaleTableFileFilter#3 - MINOR · ReadRawBinaryFilter · ReadRawBinary.cpp:96 — Preflight reads Allow Partial Filling and warns, but execute never receives it and always fails a short file (-1010).
ReadRawBinaryFilter#1 - MINOR · ReadTextDataArrayFilter · ReadTextDataArrayFilter.cpp:142 — Number of Components = 0 passes preflight and fails at execute (-263); fractional or negative tuple dimensions are cast to
usizewith no check.ReadTextDataArrayFilter#4 - MINOR · ReadZeissTxmFileFilter · ReadZeissTxmFile.cpp:138 — Preflight clamps crop bounds outside the volume (-50503 warning), but execute uses
getIndex, which fails (-33520/-33521) for the same bounds.ReadZeissTxmFileFilter#1 - MINOR · ReadZeissTxmFileFilter · ReadZeissTxmFileFilter.cpp:241 — Preflight handles only DataType 3, 5 and 10 and has no else branch; another type passes preflight with no data array and fails at execute (-33520).
ReadZeissTxmFileFilter#3 - MINOR · ResampleRectGridToImageGeomFilter · ResampleRectGridToImageGeomFilter.cpp:146 — Preflight accepts a non-Cell DataArray when tuples x components equals the cell count and only warns (-7365); a 16-tuple x 4-component array on 64 cells fails at execute (-6030).
ResampleRectGridToImageGeomFilter#2 - MINOR · SplitDataArrayByComponentFilter · SplitDataArrayByComponent.cpp:32 — Execute names outputs with
StringUtilities::number, while preflight uses the zero-paddedGenerateIndexString; any input with 11 or more components fails at execute.SplitDataArrayByComponentFilter#1 - MINOR · SplitDataArrayByTupleFilter · SplitDataArrayByTuple.cpp:566 — The NeighborList copy assumes a rank-1 tuple shape; a NeighborList in a {4,3} Attribute Matrix passes preflight and fails at execute (-2031).
SplitDataArrayByTupleFilter#3 - MINOR · WriteASCIIDataFilter · OStreamUtilities.cpp:464 — Single File mode writes float32 with 8 and float64 with 16 significant digits (not round-trip); Multiple Files mode writes the shortest round-trip form, so the last digit can differ.
WriteASCIIDataFilter#3 - MINOR · WriteImageFilter · WriteImageDirect.cpp:94 — Preflight accepts a rank-2 tuple shape when Z = 1, but execute always builds a rank-3 slice extent; the read fails at execute (-6034).
WriteImageFilter#2 - MINOR · WriteImageFilter · WriteImageFilter.cpp:252 — Preflight compares only the tuple counts of the image and mask; a mask with another tuple shape fails at execute (-6034).
WriteImageFilter#4
Already fixed or in progress
- PR BUG: Fix wrong output and invalid input handling in 19 filters #1765 (merged, commit 1986127):
ReadImageFilter#1ReadImageStackFilter#1ReadImageStackFilter#4RegularGridSampleSurfaceMeshFilter#1
- PR BUG: Fix defects in seven SimplnxCore filters #1763 (merged, commit 8bed04c):
InterpolatePointCloudToRegularGridFilter#1InterpolatePointCloudToRegularGridFilter#2
- PR BUG: Import only the GrainMapper3D IPF color datasets that exist #1839 (merged, commit 2eb6b87):
ReadGrainMapper3DFilter#6
- PR ENH: Send loop progress through the progress messaging API #1760 (merged, commit 6200001):
BadDataNeighborOrientationCheckFilter#2
- PR BUG: Fix OOC Review Findings #1764 (open, "BUG: Fix OOC Review Findings"):
ComputeKMeansFilter#6
- A fix exists on a branch that is not yet an open PR:
CropImageGeometryFilter#4
Related issues
- BUG: Skip only unused features in 2D moment calculations #1775 "BUG: Skip only unused features in 2D moment calculations" (same defect as
ComputeMomentInvariants2DFilter#1).
Out of scope
- 14 findings of this class are in 11 filters that have a V&V report. They are excluded here and are handled on a separate V&V branch:
ComputeAvgOrientationsFilter,ComputeFeatureNeighborsFilter,ComputeFeatureReferenceMisorientationsFilter,ComputeFeatureSizesFilter,ComputeKernelAvgMisorientationsFilter,DBSCANFilter,IdentifySampleFilter,NeighborOrientationCorrelationFilter,ReadAngDataFilter,RemoveFlaggedFeaturesFilter,WritePoleFigureFilter. - Findings already fixed on develop or in an open PR (listed above).
- Missing tuple-count or component-shape checks on input DataArrays are separate classes, unless the checklist names them here.
Activity
[-]BUG: Preflight/execute or Direct/Scanline disagree in 53 filters[/-][+]BUG: C07: Preflight/execute or Direct/Scanline disagree in 53 filters[/+]imikejackson commentedon Oct 23, 2026
Another preflight/execute disagreement, found during the review of #1840. This filter has a V&V report, so it may already be on the separate V&V list. If so, please ignore this comment.
NeighborOrientationCorrelationFilter: preflight reports the wrong Attribute Matrix as modified (MINOR)
nx::core::AppendDataObjectModifications(dataStructure, resultOutputActions.value().modifiedActions, imageGeom.getCellDataPath(), {});GenerateTransferArrayListbuilds.preflightResult.outputActions.value().modifiedActionsnames that matrix's arrays and does not name the Cell Data arrays.