{"record":{"id":"07736a92285fbe2c","repo":"different-ai/openwork","slug":"configuration","errorCode":"CONFIGURATION","errorMessage":"Probe timeout must be an integer from 50 through 120000 milliseconds","messagePattern":"Probe timeout must be an integer from 50 through 120000 milliseconds","errorType":"exception","errorClass":"ProbeFailure","httpStatus":null,"severity":"error","filePath":"packages/enterprise-mcp-mock-server/src/testing/probe.ts","lineNumber":419,"sourceCode":"  }\n  if (code === \"PROVIDER_DUPLICATE_REQUEST\") {\n    return new ProbeFailure(\"PROVIDER_EXECUTION\", \"provider_duplicate_request\", \"The gateway amplified one MCP tool call into duplicate requests\")\n  }\n  return new ProbeFailure(\"MCP_TOOL_EXECUTION\", \"mcp_tool\", `Provider returned tool error '${code}'`)\n}\n\nexport async function probeEnterpriseMcpMockServer(options: ProbeEnterpriseMcpMockServerOptions): Promise<ProbeResult> {\n  const diagnosticId = randomUUID()\n  const scenario = scenarioSchema.parse(options.scenario)\n  const profile = getProviderProfile(scenario.profileId)\n  const activeFault = scenario.activeFault ? getFaultDefinition(scenario.activeFault.id) : undefined\n  const mode = options.mode ?? \"fixture-conformance\"\n  const baseUrl = new URL(options.baseUrl)\n  assertLocalProbeBase(baseUrl)\n  const mcpUrl = new URL(profile.endpointPath, baseUrl).href\n  const timeoutMs = options.timeoutMs ?? 30_000\n  if (!Number.isInteger(timeoutMs) || timeoutMs < 50 || timeoutMs > 120_000) {\n    throw new ProbeFailure(\"CONFIGURATION\", \"configuration\", \"Probe timeout must be an integer from 50 through 120000 milliseconds\")\n  }\n  const overallDeadline = Date.now() + timeoutMs\n  const phases: ProbePhaseResult[] = []\n  const mutable: MutableProbeState = { negotiatedProtocolVersion: null, toolCount: 0 }\n  const sensitiveValues = [options.credentials?.clientSecret ?? \"\"]\n  let sessionId = \"\"\n  let accessToken = \"\"\n  let refreshToken = \"\"\n  let revocationClientId = scenario.oauth.clientId\n  let revocationClientSecret = options.credentials?.clientSecret ?? \"\"\n  let negotiatedProtocolHeader = \"\"\n  let revocationEndpoint: URL | null = null\n  const cleanup = async (requireValidDelete: boolean): Promise<void> => {\n    const cleanupDeadline = Date.now() + 2_000\n    if (sessionId && accessToken && negotiatedProtocolHeader) {\n      try {\n        const deleteResponse = await fetchStep(mcpUrl, {\n          method: \"DELETE\",","sourceCodeStart":401,"sourceCodeEnd":437,"githubUrl":"https://github.com/different-ai/openwork/blob/2b7df46e8ae1517d64c896c7793d2d52ec845669/packages/enterprise-mcp-mock-server/src/testing/probe.ts#L401-L437","documentation":"probeEnterpriseMcpMockServer validates options.timeoutMs before starting any probe phases. The probe is a bounded, deadline-driven diagnostic (each phase shares one overall deadline), so it refuses timeouts that are not integers or that fall outside 50-120000 ms; otherwise phases could either fire instantly or hang unreasonably. It throws a ProbeFailure with phase CONFIGURATION before any network activity.","triggerScenarios":"Calling probeEnterpriseMcpMockServer with timeoutMs set to a non-integer (e.g. 1500.5), below 50 (e.g. 10), above 120000 (e.g. 300000), or a NaN value passed from computed/config input.","commonSituations":"Multiplying seconds by 1000 with a fractional seconds value, loading the timeout from an env var or JSON config as a string-ish/float value, or setting an 'unlimited' style large value like Number.MAX_SAFE_INTEGER or 600000 to 'wait forever'.","solutions":["Pass an integer timeoutMs between 50 and 120000, e.g. timeoutMs: 30000.","If deriving from seconds, round: Math.round(seconds * 1000).","Omit timeoutMs entirely to use the 30-second default.","Clamp user/config input before calling: Math.min(120000, Math.max(50, value)) and check Number.isInteger."],"exampleFix":"// before\nawait probeEnterpriseMcpMockServer({ baseUrl, timeoutMs: 0.5 * 60_000 + 0.4 })\n// after\nawait probeEnterpriseMcpMockServer({ baseUrl, timeoutMs: Math.round(0.5 * 60_000) })","handlingStrategy":"validation","validationCode":"const timeoutMs = options.timeoutMs ?? 30_000\nif (!Number.isInteger(timeoutMs) || timeoutMs < 50 || timeoutMs > 120_000) {\n  throw new RangeError(`timeoutMs must be an integer from 50 through 120000, got ${timeoutMs}`)\n}\nawait probeEnterpriseMcpMockServer({ ...options, timeoutMs })","typeGuard":"function isValidProbeTimeout(v: unknown): v is number {\n  return typeof v === \"number\" && Number.isInteger(v) && v >= 50 && v <= 120_000\n}","tryCatchPattern":"try {\n  await probeEnterpriseMcpMockServer({ baseUrl, timeoutMs: 30_000 })\n} catch (e) {\n  if (e instanceof ProbeFailure && e.phase === \"CONFIGURATION\") {\n    console.error(\"Bad probe options:\", e.message)\n  } else throw e\n}","preventionTips":["Centralize timeout parsing/clamping in one helper used by all probe call sites","Never pass raw env-var or config values straight into numeric options","Prefer omitting timeoutMs to get the 30s default instead of inventing large values"],"tags":["configuration","validation","timeout"],"backgroundTag":"invalid-config-parameter","analyzedSha":"2b7df46e8ae1517d64c896c7793d2d52ec845669","analyzedAt":"2026-09-01T07:59:23.713Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}