different-ai/openwork · error · ProbeFailure
CONFIGURATION
CONFIGURATION
Error message
Probe timeout must be an integer from 50 through 120000 milliseconds
What it means
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.
Source
Thrown at packages/enterprise-mcp-mock-server/src/testing/probe.ts:419
}
if (code === "PROVIDER_DUPLICATE_REQUEST") {
return new ProbeFailure("PROVIDER_EXECUTION", "provider_duplicate_request", "The gateway amplified one MCP tool call into duplicate requests")
}
return new ProbeFailure("MCP_TOOL_EXECUTION", "mcp_tool", `Provider returned tool error '${code}'`)
}
export async function probeEnterpriseMcpMockServer(options: ProbeEnterpriseMcpMockServerOptions): Promise<ProbeResult> {
const diagnosticId = randomUUID()
const scenario = scenarioSchema.parse(options.scenario)
const profile = getProviderProfile(scenario.profileId)
const activeFault = scenario.activeFault ? getFaultDefinition(scenario.activeFault.id) : undefined
const mode = options.mode ?? "fixture-conformance"
const baseUrl = new URL(options.baseUrl)
assertLocalProbeBase(baseUrl)
const mcpUrl = new URL(profile.endpointPath, baseUrl).href
const timeoutMs = options.timeoutMs ?? 30_000
if (!Number.isInteger(timeoutMs) || timeoutMs < 50 || timeoutMs > 120_000) {
throw new ProbeFailure("CONFIGURATION", "configuration", "Probe timeout must be an integer from 50 through 120000 milliseconds")
}
const overallDeadline = Date.now() + timeoutMs
const phases: ProbePhaseResult[] = []
const mutable: MutableProbeState = { negotiatedProtocolVersion: null, toolCount: 0 }
const sensitiveValues = [options.credentials?.clientSecret ?? ""]
let sessionId = ""
let accessToken = ""
let refreshToken = ""
let revocationClientId = scenario.oauth.clientId
let revocationClientSecret = options.credentials?.clientSecret ?? ""
let negotiatedProtocolHeader = ""
let revocationEndpoint: URL | null = null
const cleanup = async (requireValidDelete: boolean): Promise<void> => {
const cleanupDeadline = Date.now() + 2_000
if (sessionId && accessToken && negotiatedProtocolHeader) {
try {
const deleteResponse = await fetchStep(mcpUrl, {
method: "DELETE",View on GitHub (pinned to 2b7df46e8a)
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.
Example fix
// before
await probeEnterpriseMcpMockServer({ baseUrl, timeoutMs: 0.5 * 60_000 + 0.4 })
// after
await probeEnterpriseMcpMockServer({ baseUrl, timeoutMs: Math.round(0.5 * 60_000) }) Defensive patterns
Strategy: validation
Validate before calling
const timeoutMs = options.timeoutMs ?? 30_000
if (!Number.isInteger(timeoutMs) || timeoutMs < 50 || timeoutMs > 120_000) {
throw new RangeError(`timeoutMs must be an integer from 50 through 120000, got ${timeoutMs}`)
}
await probeEnterpriseMcpMockServer({ ...options, timeoutMs }) Type guard
function isValidProbeTimeout(v: unknown): v is number {
return typeof v === "number" && Number.isInteger(v) && v >= 50 && v <= 120_000
} Try / catch
try {
await probeEnterpriseMcpMockServer({ baseUrl, timeoutMs: 30_000 })
} catch (e) {
if (e instanceof ProbeFailure && e.phase === "CONFIGURATION") {
console.error("Bad probe options:", e.message)
} else throw e
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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'.
Understand the failure class
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
- Agent context diagnostics timeout must be between 1 ms and 3
- DEN_API_PUBLIC_URL cannot contain credentials, a query strin
- Manual OIDC configuration requires authorization, token, and
- Invalid IANA timezone: ${timezone}
- ${name} must be a safe integer greater than or equal to ${mi
AI-assisted analysis of different-ai/openwork@2b7df46e8a (2026-09-01).
Data as JSON: /api/errors/07736a92285fbe2c.
Report an issue: GitHub.