Skip to content

Commit 9f2ed1c

Browse files
fix(guardrails): handle stdin EPIPE in PII python spawns
Attach an 'error' listener to the child's stdin in both runPythonScript (the batch masking hot path) and executePythonPIIDetection. A 256KB chunk can exceed the OS pipe buffer, so if the Python process exits mid-read (OOM/kill) the EPIPE emitted on stdin was unhandled and would crash the Node process. Funnel it into the promise rejection so the fail-safe scrub path handles it gracefully.
1 parent a0de0f3 commit 9f2ed1c

1 file changed

Lines changed: 14 additions & 0 deletions

File tree

apps/sim/lib/guardrails/validate_pii.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,14 @@ function runPythonScript<T>(payload: Record<string, unknown>): Promise<T> {
150150
reject(new Error('PII processing timeout'))
151151
}, DEFAULT_TIMEOUT)
152152

153+
// stdin errors (e.g. EPIPE when the child exits before draining the payload —
154+
// chunks can exceed the OS pipe buffer) emit on stdin, not the process. Without
155+
// a listener Node throws an unhandled 'error' and crashes; funnel it into the
156+
// promise so the caller's fail-safe scrub path handles it.
157+
python.stdin.on('error', (error: Error) => {
158+
clearTimeout(timeout)
159+
reject(new Error(`PII script stdin error: ${error.message}`))
160+
})
153161
python.stdin.write(JSON.stringify(payload))
154162
python.stdin.end()
155163
python.stdout.on('data', (data) => {
@@ -226,6 +234,12 @@ async function executePythonPIIDetection(
226234
mode,
227235
language,
228236
})
237+
// See runPythonScript: stdin errors (EPIPE on early child exit) must be
238+
// caught here or Node throws an unhandled 'error' and crashes the process.
239+
python.stdin.on('error', (error: Error) => {
240+
clearTimeout(timeout)
241+
reject(new Error(`Failed to write to Python: ${error.message}`))
242+
})
229243
python.stdin.write(inputData)
230244
python.stdin.end()
231245

0 commit comments

Comments
 (0)