hackmdio / hackmdio/api-client

PATCH /notes/:noteId intermittently returns 500 after ~6 seconds with no body detail

Aperta
#51 0 commenti 0 reazioni 0 assegnatari Vedi su GitHub
Lingua principale
TypeScript
Stelle
19
Fork
8
Metriche di merge delle PR
Nessuna PR unita negli ultimi 30g

Descrizione

## Summary

Calls to `PATCH /v1/notes/:noteId` intermittently return HTTP **500** with the body `{"error":"Failed to update note"}`. The failure is not deterministic — the exact same request succeeds when retried 1–2 seconds later. The issue resolves itself within a minute.

## Endpoint

```
PATCH https://api.hackmd.io/v1/notes/
```

## Request details

| Field | Value |
|-------|-------|
| Method | `PATCH` |
| Content-Type | `application/json` |
| Authorization | `Bearer ` (valid, same token works immediately after) |
| Body | `{ "content": "" }` |
| Protocol | HTTP/3 |
| TLS | TLSv1.3 |

## Observed response

```
HTTP/1.1 500 Internal Server Error
Content-Type: application/json

{"error":"Failed to update note"}
```

## Timing evidence

From Cloudflare Worker logs (the request is routed through a Cloudflare Worker CORS proxy before reaching the HackMD API):

| Metric | Value |
|--------|-------|
| Worker CPU time | ~0 ms (proxy only, no compute) |
| Wall time (total round-trip) | **~6,072 ms** |
| Worker outcome | `ok` (worker completed normally) |
| Response status received from HackMD | `500` |

The 6-second wall time indicates the HackMD backend held the connection open before returning the 500 — this is not a timeout on the client side.

## Reproduction pattern

- Frequency: Occasional, roughly 1 in 20–30 PATCH calls during normal use
- Recovery: Retrying the identical request 1.5–2 seconds later succeeds
- The note content is valid markdown (plain text, checkboxes, headings)
- The note is owned by the authenticated user — no permission issues

## What is NOT the cause

- ❌ Invalid token — the same token succeeds immediately on retry
- ❌ Permission / ownership — same note, same token works after retry
- ❌ Malformed body — same payload succeeds on retry
- ❌ Client-side timeout — the server held the connection for 6 seconds before responding 500
- ❌ CORS proxy issue — the proxy passes the request and response through transparently; its own outcome is `ok`
- ❌ Rate limiting — there is no burst of requests, this happens on isolated single saves

## Impact

Users see a "Save failed" error and must manually retry. With a client-side retry in place the error is hidden, but the underlying instability means saves are silently slower and occasionally double-charged against any rate limits.

## Request

1. Investigate whether the backend experiences transient write failures on the note storage layer
2. If a 500 is unavoidable, consider returning a `503 Service Unavailable` with a `Retry-After` header so clients can back off intelligently
3. A more descriptive error body (e.g. the underlying cause) would help distinguish storage errors from permission or validation errors

## Environment

- API version: v1
- Client: browser (Chrome 145, macOS)
- Region inferred from Cloudflare colo: `MRS` (Marseille edge, request origin: Egypt)

## Test
- You can test it on this repo https://github.com/Arigatouz/ali-productive-board where i use HackMD like. DB
- Here is a live version of it https://arigatouz.github.io/ali-productive-board/

Guida per i contributori

Nessuna guida per i contributori indicizzata per questo repository

Direzione di ricerca

Start with the PATCH /v1/notes/:noteId request path and reproduce the intermittent failure using the timing and retry pattern described. Trace the request through the API client and backend boundary, then use the response status, delay, and storage-layer behavior to identify the failure; done means a confirmed cause and an appropriate stable error response or documented fix.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Valutazione

Stack tecnologico
typescript
Ambito
api, backend
Tipo di issue
Bug
Difficoltà
4/5
Tempo stimato
3-5 giorni
Stato di attività
Tranquilla
Chiarezza
Abbastanza chiara
Idoneità per principianti
45/100

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.