koala73/worldmonitor · error · Error

Cloudflare ${method} ${path} did not complete (a write may s

Error message

Cloudflare ${method} ${path} did not complete (a write may still have landed): ${error.message}

What it means

cloudflareRequest wraps fetch calls to the Cloudflare API. When a request times out (AbortSignal.timeout) or fails at the transport level, it rethrows with the method, path, and original error. The message deliberately warns that for a write, the operation may still have landed server-side despite the client not seeing a response, so the operator must re-read state before retrying.

Solutions

  1. Before retrying a write, GET the target ruleset/rule to check whether the write already landed.
  2. Increase timeoutMs or fix network connectivity if timeouts are frequent.
  3. Retry idempotent reads freely; for writes, make the retry idempotent (same body) only after confirming current state.
  4. Check Cloudflare API status if many requests time out at once.

Example fix

// before
await cloudflareRequest(path, { method: 'PATCH', body, timeoutMs: 2000 });
// after
try {
  await cloudflareRequest(path, { method: 'PATCH', body, timeoutMs: 10000 });
} catch (e) {
  const current = await cloudflareRequest(readPath, { method: 'GET' });
  if (!matchesDesiredState(current)) throw e;
}
Defensive patterns

Strategy: try-catch

Validate before calling

// pre-flight connectivity probe before writes
const probe = await fetch('https://api.cloudflare.com/client/v4/user/tokens/verify', { signal: AbortSignal.timeout(5000) });
if (!probe.ok) throw new Error('Cloudflare API unreachable; skipping write');

Try / catch

try {
  await cloudflareRequest(path, { token, method: 'PATCH', body, fetchImpl });
} catch (e) {
  if (e.message.includes('did not complete (a write may still have landed)')) {
    const current = await cloudflareRequest(readPath, { token, fetchImpl }); // re-read before retry
    if (!stateMatchesIntent(current)) throw e;
    return; // write had landed
  }
  throw e;
}

Prevention

When it happens

Trigger: The fetch to /zones/.../rulesets/... times out via AbortSignal.timeout(timeoutMs), the connection is reset, DNS fails, or TLS/transport errors occur mid-request.

Common situations: Slow or flaky network to api.cloudflare.com, an overly tight timeoutMs, corporate proxy interference, or a Cloudflare API incident causing long latency on a PATCH/POST write.

Understand the failure class

Background: Request timed out: what client-side request timeouts mean across libraries (Request timed out, TIMED_OUT, APITimeoutError) — this error's family across 39 libraries.

Related errors


AI-assisted analysis of koala73/worldmonitor@7d06c8633d (2026-09-15). Data as JSON: /api/errors/8d0de6d25051a698. Report an issue: GitHub.

Appendix: source

Thrown at scripts/cloudflare-cache-rule.mjs:502

) {
  // A hung API call must not park an `--apply` between the read and the write
  // forever; fail loudly instead so the operator can retry against a fresh read.
  let response;
  try {
    response = await fetchImpl(`${CLOUDFLARE_API}${path}`, {
      method,
      headers: {
        Authorization: `Bearer ${token}`,
        'User-Agent': USER_AGENT,
        ...(body ? { 'Content-Type': 'application/json' } : {}),
      },
      ...(body ? { body: JSON.stringify(body) } : {}),
      signal: AbortSignal.timeout(timeoutMs),
    });
  } catch (error) {
    // A timeout or transport failure on a write is ambiguous — the write may
    // still have landed — so name the request the operator has to re-read for.
    throw new Error(`Cloudflare ${method} ${path} did not complete (a write may still have landed): ${error.message}`);
  }
  const payload = await response.json().catch(() => null);
  if (!response.ok || !payload?.success) {
    const detail = JSON.stringify(payload?.errors ?? payload ?? response.statusText);
    throw new Error(`Cloudflare ${method} ${path} failed (${response.status}): ${detail}`);
  }
  return payload.result;
}

export async function resolveZoneId(token, { env = process.env, fetchImpl } = {}) {
  if (env.CLOUDFLARE_ZONE_ID) {
    // Never take the id on trust. The credential that actually runs this locally
    // is account-wide, so a stale or mistyped id would aim every write at another
    // zone's cache rules — and the script would report success.
    const zone = await cloudflareRequest(`/zones/${encodeURIComponent(env.CLOUDFLARE_ZONE_ID)}`, {
      token,
      fetchImpl,
    });

View on GitHub (pinned to 7d06c8633d)