fix(execute-command): cap timeout at MAX_DURATION, simplify error handler, document workingDirectory

- Enforce upper bound on timeout (MAX_DURATION - 10s) to prevent orphan processes
- Remove unreachable throw branch in handler — always return structured data
- Document that workingDirectory does not support variable references

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Waleed Latif
2026-03-05 15:14:15 -08:00
parent 5782b6830e
commit 448548ec31
3 changed files with 9 additions and 8 deletions

View File

@@ -333,8 +333,12 @@ export async function POST(req: NextRequest) {
workflowId,
} = body
const MAX_ALLOWED_TIMEOUT_MS = (MAX_DURATION - 10) * 1000
const parsedTimeout = Number(body.timeout)
const timeout = parsedTimeout > 0 ? parsedTimeout : DEFAULT_EXECUTION_TIMEOUT_MS
const timeout = Math.min(
parsedTimeout > 0 ? parsedTimeout : DEFAULT_EXECUTION_TIMEOUT_MS,
MAX_ALLOWED_TIMEOUT_MS
)
if (!command || typeof command !== 'string') {
return NextResponse.json(

View File

@@ -16,7 +16,7 @@ export const ExecuteCommandBlock: BlockConfig<ExecuteCommandOutput> = {
- Chain multiple commands with && to run them sequentially.
- Use <blockName.output> syntax to reference outputs from other blocks.
- Use {{ENV_VAR}} syntax to reference environment variables.
- The working directory defaults to the server process directory if not specified.
- The working directory defaults to the server process directory if not specified. Variable references are not supported in the Working Directory field — use a literal path.
- A non-zero exit code is returned as data (exitCode > 0), not treated as a workflow error. Use a Condition block to branch on exitCode if needed.
- Variable values from other blocks are interpolated directly into the command string. Avoid passing untrusted user input as block references to prevent shell injection.
`,

View File

@@ -44,13 +44,10 @@ export class ExecuteCommandBlockHandler implements BlockHandler {
)
if (!result.success) {
if (result.output) {
return {
...result.output,
error: result.error || 'Command execution failed',
}
return {
...(result.output ?? { stdout: '', stderr: '', exitCode: 1 }),
error: result.error || 'Command execution failed',
}
throw new Error(result.error || 'Command execution failed')
}
return { ...result.output, error: null }