Build1 distinct publisher3 min readUpdated
A European weather archive retrained the model behind its code assistant and found the training set had taught it to call a variable the API never served. Drift does not stay in the docs.
The Engineer · Build desk

Compiled by The EngineerSomething wrong?How this is made
The operator of dailymeteo.com sat down to retrain the fine-tuned GPT model behind its natural-language chat endpoint and found that the training data had been teaching the model to call an API parameter that returns 400 [1][2][3]. The training set had been written from the API documentation, and, as the dev.to write-up puts it, documentation is a claim about a system rather than the system [4][5].
The service is a daily meteorological archive for Europe, gridded at 1 km, running from 1961 to roughly five days ago, with a chat endpoint that turns a plain-language question into R code against the archive [1]. Behind that sits a fine-tuned model trained on a few hundred question-and-code pairs [2]. The plan for the day was hyperparameters; the day went instead to measuring what the API actually returns, and three documented claims turned out to be wrong [6][7].
The clearest case is `slp`, sea-level pressure. The documentation lists it as available [8]. There are 21,916 daily rasters on disk covering 1961 to 2020 [9], which is within a day of complete daily coverage for those 60 years [10]. The API will not serve any of them: an allow-list of `['tmax','tmin','tmean','prcp']` guards every entry point, and the continent mapping points at a newer data folder that never received the pressure rasters, so there are two independent reasons for the same 400 [11][12]. The error message returned on failure still lists `slp` among the valid options, because the message is older than the list [13]. Two training examples asked for it, so on any pressure question the model emitted confident, well-formed, non-functional code [14][15].
The other failures are the same shape. A request for 1960 returns "There's no data for date range" because the archive begins in 1961, while the recent end moves: daily to about five days ago, monthly to the previous month, annual to the last complete year [16][17]. Any fixed end year written into a system prompt is silently wrong within twelve months [18], and several training examples hardcoded one [19]. The measurement also surfaced a better pattern: out-of-range requests are not errors, they clip, so `ann 1961 -> 2035` came back as 1961 to 2025 and `mon 1961-01 -> 2030-12` came back through 2026-07 [20][21]. Generated code can ask wide and read the real extent out of the response instead of guessing [22]. Those two clipped values are internally consistent with a measurement taken in August 2026 [23].
Two more, both about conventions nobody wrote down. For long-term means the returned timestamp carries a climate period, not a date, so it reads `1961-1990` or `25.07.1991-2020`, and code doing `substr(timestamp, 1, 4)` to pull a year gets nonsense, which some of theirs did [24][25]. Long-term means had no description in the docs at all, and across 23 calls in the training set they were invoked seven different ways, two mutually contradictory, so the model learned that no convention exists [26][27]. Separately, 28 examples pinned an arbitrary year the question never specified, such as autumn in Prague fetched as 1999-09-01 to 1999-11-30 [28][29].
Worth checking on your own stack: whether your error strings and your allow-lists were last edited in the same year, and whether your examples encode extents that your API will happily report back if asked.
Follow any of these and your For You feed starts watching them — no settings page required.
Ranked by verification strength, evidence, and original report placement.
Writing a fixed end year into a system prompt guarantees it will be wrong within twelve months, silently.
One training example asked about plotting temperatures during autumn (September 1 to November 30) in Prague and answered with from = "1999-09-01", to = "1999-11-30"; the question did not specify a year and the example writer picked one.
There were 28 training examples that pinned an arbitrary year not specified by the question.
dailymeteo.com is a daily meteorological archive for Europe, gridded at 1 km, running from 1961 to roughly five days ago, with a chat endpoint where a plain-language question returns R code that queries the archive.
Behind the chat endpoint sits a fine-tuned GPT model trained on a few hundred question-and-code pairs.
The author set out to retrain the model on a better dataset and instead found the model had been taught things that were not true.
Evidence-backed comparisons of source perspectives and observed adoption signals. Read the methodology
Which Builder, Operator, and Investor concerns the observed source mix emphasized—not a truth score.
Evidence, demonstrated adoption, hype gap, incentives, and confidence are assessed independently, each on its own current evidence. How these are measured.
Concrete first-party measurements, zero external verification
Unusually specific for a single-source story: verbatim request/response probes, the allow-list literal from the view code, raster and example counts, and training-step loss values. All of it, however, comes from one operator writing about his own system, and no second party reproduced any probe, so the ceiling is the author's own accuracy and candour.
One self-disclosed deployment
Adoption evidence is confined to a single operator's own production endpoint and its own training-set audit. There is no second team reporting the same docs-drift failure, no released tooling, downloads, or usage figures, and no benchmark others can run, so the practice described has no observable uptake beyond its author.
Findings modest and evidenced; generality is asserted, not shown
The specific claims are narrow, self-critical, and backed by measurements, which pushes toward alignment. The mild overstatement is generalisation: the author suspects docs-derived fine-tuning drift is 'extremely common' and the cluster framing treats one archive's audit as a broad pattern, while the evidence base remains a single deployment with no second case.
Operator writing about own product, but disclosure is unflattering
The author has a visibility incentive: the post names and links his commercial archive service on a developer platform. That is offset because the content documents his own broken endpoint, stale error message, and defective training data — an admission that cuts against promotional framing. No vendor sponsorship, pricing pitch, or third-party product endorsement appears.
Internally consistent single account
Moderate. The account is coherent and internally cross-checks (the monthly clip to 2026-07 matches the stated cadence and the publication date; the raster count matches the 1961-2020 span), and the level of specificity would be costly to fabricate. But everything rests on one unverified first-party post, key context is absent (base model, whether the docs were fixed, post-fix evaluation), so confidence cannot rise further.
build
The stopping problem: an LLM rewrite loop that converged on code javac rejected1 distinct publisher
build
Force the tool call, then hand Lightsail a long-lived key1 distinct publisher
build
AI-written code fails the same four ways, and every gate you own reports green1 distinct publisher
build
CSA's 2026 threat list is a flat line, so ask which threats a config snapshot can prove1 distinct publisher
Distinct publishers with included, body-backed reporting in this cluster.
dev.to
1 article · August 19, 2026