MockReader splits mocks.yaml on indented '---', so keploy cannot read back a file it wrote (replay session fails to start)
Summary
MockReader splits mocks.yaml on any line whose trimmed content is ---.
A YAML document separator is only a separator at column 0, so an indented
--- inside a block scalar is mistaken for one. The reader then hands a
truncated fragment to the YAML parser and the whole test set fails to load.
The practical effect is that keploy writes a mocks.yaml it cannot read back,
and the replay session never starts — so zero tests run, and (because the upload
is downstream of the replay) the test set is never uploaded, which makes
keploy cloud replay impossible for that recording too.
Root cause
pkg/platform/yaml/mockreader.go, readNextYAMLDocument():
trimmedLine := strings.TrimSpace(line)
if trimmedLine == "---" {
if buffer.Len() == 0 {
continue
}
return buffer.Bytes(), nil
}strings.TrimSpace removes leading whitespace too, so --- (inside a
body: |+ block scalar) compares equal to "---" and terminates the document.
Reproduction
Record any request whose captured body contains a line that is --- after
trimming. We hit it recording an LLM-backed flow, because --- is ubiquitous in
prompts, but it needs nothing exotic — markdown, YAML payloads, front-matter or
an email separator will do it.
Observed with an ATG generation recording (4 test cases, 236 mocks):
ERROR utils/utils.go:314 failed to unmarshal a mock yaml doc of unknown type {"type": ""}
ERROR utils/utils.go:314 failed to get filtered mocks
ERROR utils/utils.go:314 failed to run test set: failed to decode the file documents.
error: failed to decode YAML at line 5480: yaml: line 8: mapping values are not allowed in this context
ERROR replay/replay.go:1515 replay session failed to startReproduced twice; the offset tracks the recorded content (line 5480, then 5484).
The offending mock is the outbound Azure OpenAI call:
kind: Http2
spec:
req:
method: POST
url: /openai/v1/responses
authority: keploy-llm-temp.cognitiveservices.azure.com
body: |+
...
--- <-- line 5449, indented, inside the block scalar
...
--- <-- line 5475The file itself is valid — this is reader-side only
$ python3 -c "import yaml; print(len(list(yaml.safe_load_all(open('mocks.yaml')))))"
236yaml.safe_load_all parses all 236 documents cleanly
(DNS: 8, Mongo: 222, Http2: 4, Http: 2). A conformant parser honours block-scalar
indentation; only the hand-rolled line splitter does not. So the writer is fine
and nothing already recorded is lost — those files become readable again as soon
as the reader is fixed.
Suggested fix
Only strip trailing whitespace, so column-0 anchoring is preserved:
// A YAML document separator is only a separator at column 0. TrimSpace also
// removes leading whitespace, which makes an indented "---" inside a block
// scalar (e.g. a recorded body containing markdown) look like a new document.
trimmedLine := strings.TrimRight(line, " \t\r\n")
if trimmedLine == "---" {Note trimmedLine is also used two lines below for the # comment check; that
one wants a leading-trimmed value, so the two uses should be separated rather
than sharing one variable.
Worth a regression test: a mock whose body is a block scalar containing an
indented ---, asserted to round-trip through MockReader.
Impact
High. It is silent (nothing warns at record time), it takes out the entire test
set rather than one test case, and it blocks cloud replay as a knock-on because
the upload never happens. Any app whose traffic can contain a --- line is
exposed, and LLM-backed flows essentially always are.
Environment
- keploy enterprise 3.7.23 (CLI), k8s-proxy DaemonSet mode, kind cluster
- api-server
v1.8.13, recordingprod/api-server
Source: keploy/keploy