Skip to content

Commit 8812340

Browse files
committed
fix(input-format): require run-ready file shape, don't clobber named files input
Addresses review (Greptile P1s): - parseInputFormatFiles now requires the full run-ready shape (id/name/url + finite size + type), so a partial file can't open in uploader mode or reach workflowInput.files only to be rejected by normalizeStartFile (which would silently drop every file). - buildInputFormatInput no longer overwrites a user field literally named 'files' with the upload channel; that reserved-name collision is left for the executor to surface.
1 parent f7ca85a commit 8812340

3 files changed

Lines changed: 30 additions & 9 deletions

File tree

apps/sim/app/workspace/[workspaceId]/w/[workflowId]/hooks/use-workflow-execution.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -163,8 +163,11 @@ function buildInputFormatInput(inputFormatValue: unknown): Record<string, any> |
163163
}
164164
}
165165

166+
// Route file[] fields to the dedicated `files` channel, but never clobber a
167+
// user field that is itself named `files` (a reserved-name config error the
168+
// executor surfaces on its own).
166169
const files = collectInputFormatFiles(inputFormatValue)
167-
if (files.length > 0) testInput.files = files
170+
if (files.length > 0 && !('files' in testInput)) testInput.files = files
168171

169172
return Object.keys(testInput).length > 0 ? testInput : undefined
170173
}

apps/sim/lib/workflows/input-format.test.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -288,6 +288,17 @@ describe('parseInputFormatFiles', () => {
288288
it.concurrent('keeps only the valid files in a mixed array', () => {
289289
expect(parseInputFormatFiles(JSON.stringify([file, { name: 'bad' }]))).toEqual([file])
290290
})
291+
292+
it.concurrent('rejects partial files missing the run-ready size/type', () => {
293+
expect(parseInputFormatFiles(JSON.stringify([{ id: 'x', name: 'a.pdf', url: '/u' }]))).toEqual(
294+
[]
295+
)
296+
expect(
297+
parseInputFormatFiles(
298+
JSON.stringify([{ id: 'x', name: 'a.pdf', url: '/u', size: Number.NaN, type: 'x' }])
299+
)
300+
).toEqual([])
301+
})
291302
})
292303

293304
describe('collectInputFormatFiles', () => {

apps/sim/lib/workflows/input-format.ts

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -81,14 +81,21 @@ export function parseInputFormatFiles(value: unknown): InputFormatFile[] {
8181

8282
if (!Array.isArray(raw)) return []
8383

84-
return raw.filter(
85-
(file): file is InputFormatFile =>
86-
file !== null &&
87-
typeof file === 'object' &&
88-
typeof (file as InputFormatFile).name === 'string' &&
89-
typeof (file as InputFormatFile).url === 'string' &&
90-
typeof (file as InputFormatFile).id === 'string'
91-
)
84+
return raw.filter((file): file is InputFormatFile => {
85+
if (file === null || typeof file !== 'object') return false
86+
const f = file as InputFormatFile
87+
// Require the full run-ready shape the executor's normalizeStartFile needs,
88+
// so a partial object never opens in uploader mode or reaches the files
89+
// channel only to be rejected (which would silently drop every file).
90+
return (
91+
typeof f.id === 'string' &&
92+
typeof f.name === 'string' &&
93+
typeof f.url === 'string' &&
94+
typeof f.size === 'number' &&
95+
Number.isFinite(f.size) &&
96+
typeof f.type === 'string'
97+
)
98+
})
9299
}
93100

94101
/**

0 commit comments

Comments
 (0)