Trace a broken umlaut to a streaming byte boundary
If an application displays “Pr��fung” where the source says “Prüfung,” changing the font or rewriting the source text may not address the cause. The bytes can be correct while the receiving code handles an arbitrary network chunk as though it were a complete text unit.
This fictional status panel receives UTF-8 text from an internal service. The stored value and complete response bytes are correct. The defect appears only when the response is delivered in particular chunks, making the same record look intermittent.
Hold the bytes constant
The word “Prüfung” has the following UTF-8 bytes in the exercise:
50 72 C3 BC 66 75 6E 67
The two bytes C3 BC represent ü. A complete decode of that sequence produces the intended word. The failing delivery divides the same bytes after C3, yielding chunks 50 72 C3 and BC 66 75 6E 67. No byte has been changed or lost.
| Observation | Result | What it rules in or out |
|---|---|---|
| Stored text | Prüfung | Source value is intact |
| Complete response decoded together | Prüfung | The full byte sequence is valid UTF-8 |
| Each chunk decoded independently with replacement behavior | Pr��fung | The chunk boundary changes decoding behavior |
| Same chunks passed through one streaming decoder | Prüfung | Preserving decoder state resolves this fixture |
The old code creates a new decoder for each chunk. The first decoder sees an incomplete sequence at its end; the second sees a continuation byte without its beginning. With replacement behavior, each produces a replacement character. Joining the resulting strings cannot reconstruct the lost decoding context.
Repair the decoding boundary
The receiving code retains one UTF-8 decoder across the chunks of the same response. It feeds each chunk with streaming enabled, then performs a final decode to flush the completed stream. The WHATWG Encoding Standard defines this streaming behavior and the optional fatal error policy.
The exercise chooses fatal handling for malformed input so a genuinely invalid response is reported rather than silently presented as trustworthy status text. With that policy, valid split input is accepted because the decoder retains the incomplete sequence until its remaining byte arrives. The final flush is still necessary: it distinguishes a temporarily incomplete chunk from an incomplete response that has actually ended.
Decoder state belongs to one response. Reusing it across unrelated responses would create a different boundary error. The correction therefore specifies both the lifetime of the decoder and the point at which completion or failure is reported to the panel.
Verify content and refusal behavior
The exact complete and split byte fixtures now both produce “Prüfung.” An ASCII control, “Review,” remains unchanged. The stored source, request reference and response bytes remain untouched; the repair occurs in the receiving text-decoding step.
A malformed sequence C3 28 fails under the chosen fatal policy. A response that ends with an unmatched C3 also fails at final flush. The interface reports that the status text could not be read and retains a route for investigation; it does not guess the missing character or mark the underlying work approved. These controls show that success was not achieved by accepting any byte sequence indiscriminately.
The review record includes the exact bytes, chunk boundaries, decoder policy and final result. It identifies the runtime used for the demonstration. It does not establish every browser, transport or source system's behavior from this small fixture.
Use the first disagreement to guide the next check
For a similar problem, compare the source value, complete bytes and rendered text before applying a broad encoding conversion. If complete decoding is correct but chunked decoding is not, examine state across the receiving boundary. If the complete bytes are already wrong, the investigation belongs earlier in the path.
Integration work should make such boundaries inspectable. A precise reproduction can prevent a local display fault from becoming an unnecessary database cleanup, font replacement or source-content rewrite.