cloudflare / cloudflare/workerd

🐛 Bug Report — Runtime APIs: `KvNamespace#put()` hangs if body not consumed and error response returned

Open
#960 1 comment 0 reactions 0 assignees View on GitHub
Dominant language
C++
Stars
8.7k
Forks
739
Avg merge
2d 20h
Merged PRs (30d)
174

Description

Hey! 👋 With the following `workerd` configuration...

```capnp
using Workerd = import "/workerd/workerd.capnp";

const config :Workerd.Config = (
services = [
( name = "main", worker = .worker ),
( name = "kv", worker = .kvWorker ),
],
sockets = [
( name = "http", address = "*:8080", http = (), service = "main" ),
]
);

const worker :Workerd.Worker = (
compatibilityDate = "2023-08-01",
modules = [ ( name = "index.mjs", esModule = embed "index.mjs" ) ],
bindings = [
( name = "NAMESPACE", kvNamespace = "kv" ),
],
);

const kvWorker :Workerd.Worker = (
compatibilityDate = "2023-08-01",
modules = [ ( name = "kv.mjs", esModule = embed "kv.mjs" ) ],
);
```

```js
// index.mjs
export default {
async fetch(request, env, ctx) {
try {
await env.NAMESPACE.put("key", "value", { expirationTtl: 1 });
return new Response("OK");
} catch (e) {
return new Response("Internal Server Error: " + e.stack, { status: 500 });
}
}
}
```

```js
// kv.mjs
export default {
async fetch(request, env, ctx) {
const url = new URL(request.url);
const expirationTtlHeader = url.searchParams.get("expiration_ttl");
if (expirationTtlHeader !== null) {
const expirationTtl = parseInt(expirationTtlHeader);
if (expirationTtl < 60) {
/* (1) */ await request.arrayBuffer(); // Without this, just hangs
return new Response("Invalid expiration_ttl of 1. Expiration TTL must be at least 60.", {
status: 400,
statusText: "Invalid expiration_ttl of 1. Expiration TTL must be at least 60."
});
}
}

// Pipe the body somewhere
/* (2) */ await request.arrayBuffer(); // Without this, `Error: Network connection lost.`
return new Response();
}
}
```

...removing `/* (1) */`, and passing `{ expirationTtl: 1 }` as above, the request will just hang. I'd expect `Internal Server Error: Error: KV PUT failed: 400 Invalid expiration_ttl of 1. Expiration TTL must be at least 60.` to be returned as the response here.

Removing `/* (2) */` instead and passing a valid `expirationTtl` results in `kj/async-io.c++:631: disconnected: read end of pipe was aborted` logged with `Internal Server Error: Error: Network connection lost.` returned as the response. I'd expect `OK` to be returned as the response here.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.