{"record":{"id":"0ba7f976f90c37b0","repo":"Tencent/WeKnora","slug":"e2b-timeout-must-be-at-least-one-second","errorCode":null,"errorMessage":"E2B timeout must be at least one second","messagePattern":"E2B timeout must be at least one second","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/sandbox/e2b_remote_client.go","lineNumber":1084,"sourceCode":"\t\t// image orphan cleanup. Fail fast instead of hanging until cancel.\n\t\tif _, dup := seen[page.NextToken]; dup {\n\t\t\treturn nil, e2bInvalidRequest(\"ListSnapshots\",\n\t\t\t\t\"provider returned a repeated pagination token\", nil)\n\t\t}\n\t\tseen[page.NextToken] = struct{}{}\n\t\ttoken = page.NextToken\n\t}\n}\n\n// --- helpers -----------------------------------------------------------------\n\n// e2bTimeoutSeconds maps the neutral RemoteTimeoutPolicy onto E2B's integer\n// timeout. E2B only supports a positive TTL; \"never\" is rejected as\n// unsupported so the lifecycle coordinator can pick a different policy.\nfunc e2bTimeoutSeconds(policy RemoteTimeoutPolicy, fallback time.Duration) (int, error) {\n\ttoSeconds := func(value time.Duration) (int, error) {\n\t\tif value > 0 && value < time.Second {\n\t\t\treturn 0, errors.New(\"E2B timeout must be at least one second\")\n\t\t}\n\t\tseconds := value / time.Second\n\t\tif value%time.Second != 0 {\n\t\t\tseconds++\n\t\t}\n\t\treturn int(seconds), nil\n\t}\n\n\tswitch policy.Mode {\n\tcase \"\", RemoteTimeoutServerDefault:\n\t\tif fallback <= 0 {\n\t\t\treturn 0, nil\n\t\t}\n\t\treturn toSeconds(fallback)\n\tcase RemoteTimeoutExplicit:\n\t\tif policy.Value < 0 {\n\t\t\treturn 0, errors.New(\"E2B backend does not support NeverTimeout\")\n\t\t}","sourceCodeStart":1066,"sourceCodeEnd":1102,"githubUrl":"https://github.com/Tencent/WeKnora/blob/988cbb03305e055d8ebb7d46d9ac6cc0803cd074/internal/sandbox/e2b_remote_client.go#L1066-L1102","documentation":"E2B exposes sandbox timeouts only as whole-second positive TTLs. e2bTimeoutSeconds rejects durations greater than zero but under one second, since they cannot be represented (E2B has no sub-second or zero TTL), so the lifecycle coordinator can fall back to a different timeout policy rather than silently truncating.","triggerScenarios":"Any operation that maps a RemoteTimeoutPolicy (Create, Connect, Get, Delete, CreateSnapshot, or the anonymous fallback mapper) where the effective duration is e.g. 500ms — either an explicit policy value < 1s or a fallback duration < 1s.","commonSituations":"Config sets very aggressive timeout values for fast tests; a caller converts a millisecond-based setting into time.Duration without enforcing a 1s floor; a sub-second fallback duration is passed to e2bTimeoutSeconds.","solutions":["Raise the configured timeout to at least 1 * time.Second","Clamp sub-second durations to 1 second before passing them to the E2B client","Use a different backend (e.g. Docker) if sub-second sandbox TTLs are genuinely required"],"exampleFix":"// before\ntimeout := 500 * time.Millisecond\n// after\ntimeout := 500 * time.Millisecond\nif timeout < time.Second {\n    timeout = time.Second\n}","handlingStrategy":"validation","validationCode":"func clampE2BTimeout(d time.Duration) time.Duration {\n    if d > 0 && d < time.Second {\n        return time.Second\n    }\n    return d\n}\n// apply before mapping policy: policy.Value = clampE2BTimeout(policy.Value)","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Enforce a 1-second floor on all E2B timeout settings at config-load time","Avoid millisecond-granularity timeout knobs for E2B sandboxes","Add a table test over e2bTimeoutSeconds covering sub-second values"],"tags":["go","sandbox","e2b","timeout","validation"],"backgroundTag":"timeout-below-minimum","analyzedSha":"988cbb03305e055d8ebb7d46d9ac6cc0803cd074","analyzedAt":"2026-09-02T14:41:08.344Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}