Migration diagnostics
Migration diagnostics — from Stainless
Migrating from Stainless translates a stainless.yml into a
glotto.yml. It is non-destructive and never silently drops anything: every key it could not
carry over is reported, so the migration report is the checklist of what still needs a human.
| Code | Severity | Meaning |
|---|---|---|
GLOTTO_MIGRATE_STAINLESS_UNMAPPED |
warning | A key in your stainless.yml has no glotto.yml equivalent, so it was dropped rather than guessed at. The path names the key (nested paths are reported in full). Review each one against the migration guide — some are Stainless-specific and safely gone, others have a different Glotto mechanism worth re-expressing by hand. |
GLOTTO_MIGRATE_STAINLESS_PLACEHOLDER |
warning | A required glotto.yml field could not be derived from the Stainless input, so the migrator wrote a placeholder value to keep the output well-formed. Replace every placeholder before running glotto generate — the config is not usable until you do. |
GLOTTO_MIGRATE_STAINLESS_STAMP_UNSUPPORTED |
error | glotto migrate stainless --openapi-out refused to rewrite your spec, and wrote neither the rewritten spec nor glotto.yml. The rewrite inserts an x-glotto-* key only into a YAML mapping written in plain style — a block mapping whose first key starts its own line, or a single-line flow mapping whose first key directly follows its { — carrying no anchor, tag, or key with an anchor, tag or alias, and reached by the document directly rather than only through an alias or a merge. Any mapping outside that set is refused, for example one carrying an anchor or tag, one with an explicit ? key or merge key <<, or a flow mapping spread over several lines. It is also refused when the stamps would break equality between repeated allOf properties, or change whether repeated additionalProperties schemas agree and therefore change the map’s value type. The message names the affected mappings or schemas. Rewrite a named YAML mapping in plain block style, or pass the spec as JSON. Declare a repeated property or additionalProperties schema once. Then run the migration again. |
The first two are warnings rather than errors because the migration itself succeeded; they describe work remaining, not a failure. Together they are the first Glotto diagnostics most migrating teams see. The third is an error: it stops the run before anything is written, so fixing it and running the migration again starts from a clean slate.
Migration diagnostics — from Fern
Migrating from Fern translates a fern/generators.yml into a
glotto.yml. Where the Stainless migrator’s report is binary — carried over, or dropped — this one
gives every input key one of four verdicts, because several Fern knobs are Glotto
guarantees: reporting those as a loss would say you are giving up a property at the moment you are
gaining a stronger version of it.
| Code | Severity | Meaning |
|---|---|---|
GLOTTO_MIGRATE_FERN_MAPPED |
info | The key was translated. The message names the glotto.yml key it became. |
GLOTTO_MIGRATE_FERN_GUARANTEED |
info | You are not losing this. Glotto provides the property unconditionally, so there is nothing to configure — the message names the guarantee (open enums, unknown-field preservation, the emitted test suite). |
GLOTTO_MIGRATE_FERN_NOT_HONORED |
info | A Fern emission-shape knob Glotto answers differently on purpose (noSerdeLayer, the pydantic_config block, union: v0|v1, …). Honoring it would mean re-implementing Fern’s emitter, so it is a deliberate non-goal rather than a gap. |
GLOTTO_MIGRATE_FERN_UNMAPPED |
warning | Genuinely no glotto.yml home, reported at its precise dotted path. This is the list that needs your attention. |
GLOTTO_MIGRATE_FERN_PLACEHOLDER |
warning | A required glotto.yml field your Fern config cannot supply (your organization details live in fern.config.json, your environments in the API definition). Replace every placeholder before running glotto generate. |
GLOTTO_MIGRATE_FERN_IGNORE |
info | A .fernignore entry. Fern freezes a listed file; Glotto three-way-merges instead, so the entry is reported with the construct that replaces it and no file is written. |
GLOTTO_MIGRATE_FERN_NAME_UNPINNED |
warning | Under --preserve-names, an emitted member name that could not be pinned to the Fern spelling — a reserved word (pinning it would emit code that does not compile), an ambiguous acronym split, the client class name, or a transparent-DTO engine. Names both spellings so nothing is left silently divergent. |
GLOTTO_MIGRATE_FERN_GROUP_AMBIGUOUS |
error | Your project declares several generator groups and no default-group, so there is nothing to migrate without a choice. Re-run with --group <id>; no file is written. |
GLOTTO_MIGRATE_FERN_DOCS_PLACEHOLDER |
warning | The docs half’s sibling of GLOTTO_MIGRATE_FERN_PLACEHOLDER: a required field of the migrated docs block your fern/docs.yml cannot supply. Today that is a docs.versions[] spec snapshot — Fern’s versions[].path names that version’s docs config, not a spec — so each entry is written with a clearly-marked TODO source for you to replace. |
GLOTTO_MIGRATE_FERN_DEFINITION_INPUT |
error | This is a Fern Definition project, not an OpenAPI one. Export the API first (fern api export --openapi) and re-run against the exported document. |
The two error codes stop the migration and write no output — half-migrating either case would
produce a config that validates but generates the wrong SDKs.
glotto migrate speakeasy
Speakeasy keeps its config in two files at two levels — one .speakeasy/workflow.yaml at your
project root, and one .speakeasy/gen.yaml beside each generated SDK — so the migration reads both
and reports against whichever file a key came from. The four verdicts mean exactly what they mean
for migrate fern above. For the walkthrough these codes come out of — what the conversion needs,
what it writes, and what to do with each verdict — see
Migrate from Speakeasy.
| Code | Severity | Meaning |
|---|---|---|
GLOTTO_MIGRATE_SPEAKEASY_MAPPED |
info | The key was translated. The message names the glotto.yml key it became. |
GLOTTO_MIGRATE_SPEAKEASY_GUARANTEED |
info | You are not losing this. Glotto provides the property unconditionally — enableCustomCodeRegions becomes a three-way merge on every regeneration, forwardCompatibleEnumsByDefault is simply how Glotto emits enums, and the emitted test suite needs no opt-in. |
GLOTTO_MIGRATE_SPEAKEASY_NOT_HONORED |
info | A Speakeasy emission-shape knob Glotto decides itself (maintainOpenAPIOrder, responseFormat, multipartArrayFormat, …), or vendor bookkeeping (management, features) that records generation checksums rather than anything you chose. A real per-language block is mostly this tier, which is why it is separated from the list below. |
GLOTTO_MIGRATE_SPEAKEASY_UNMAPPED |
warning | Genuinely no glotto.yml home, reported at its precise dotted path. This is the list that needs your attention. |
GLOTTO_MIGRATE_SPEAKEASY_PLACEHOLDER |
warning | A required glotto.yml field your Speakeasy config cannot supply — a workflow carries no organization identity and declares no API surface. Replace every placeholder before running glotto generate. |
GLOTTO_MIGRATE_SPEAKEASY_DEAD_REGISTRY |
warning | A registry.speakeasyapi.dev reference. That registry resolves against the vendor service you are leaving, so carrying it across would emit a config that validates and then fails in your CI against a 404. Export the document to a local path and re-run. |
GLOTTO_MIGRATE_SPEAKEASY_GEN_MISSING |
warning | A target whose .speakeasy/gen.yaml could not be read, naming the path that was looked for. The target is still migrated from workflow.yaml alone — but its package name and module namespace are not, so a silent partial migration never passes for a complete one. |
GLOTTO_MIGRATE_SPEAKEASY_SECRET_DROPPED |
warning | A publish credential (publish.pypi.token, …). It is deliberately never written into glotto.yml; configure it as a repository secret for the release workflow instead. Your release pipeline does not work until you do. |
GLOTTO_MIGRATE_SPEAKEASY_RESOURCE_UNNAMED |
warning | A tag in your spec carries no letters or digits (ペット, ---), so it normalises to an empty resource name — and every such tag is grouped under that one empty name together. The message names the tag it came from. Glotto deliberately does not invent a replacement: a resource key is the accessor name your SDK exposes, so guessing one would rename your surface, which is the thing a migration must not do. Rename the tag in your spec, or set the resource key by hand. |
GLOTTO_MIGRATE_SPEAKEASY_NAME_DERIVED |
warning | An operation in your spec declares no operationId, so there was no name to carry across and Glotto built one from the route (get /pets/{petId} → get_pets_petId_). That key is the method name your SDK will expose, and your current one may expose something different — rename the key in glotto.yml if so. Every operation that has an operationId keeps it, and is not reported here. |
GLOTTO_MIGRATE_SPEAKEASY_TRANSFORM_UNVERIFIED |
warning | A transform applied during the conversion, and your resources block includes its effect, but it reaches a value Glotto normalizes before applying transforms. That is an overlay action or a merge anchor that reaches an example, even through a wildcard, or a merged document that writes a server list or an example, or is anchored on a server. glotto generate compares those normalized values, so it may still refuse the transform, for example when an overlay removes an example that duplicates its sibling example. The message names the transform; run glotto generate to confirm it applies. |
GLOTTO_MIGRATE_SPEAKEASY_SURFACE_PARTIAL |
warning | Your source stacks overlays or merges further documents, and at least one could not be applied during the conversion, so your resources block describes the primary document rather than the surface Glotto generates from. An OpenAPI Overlay can add or remove an operation, so check the block against your final surface. The message names the transform and the reason: an overlay that is a URL, a file that is missing or will not parse, a Swagger 2.0 document (Glotto converts it before applying anything), an action whose JSONPath filter may read a server URL or an example (Glotto normalizes those values before applying overlays, so the selection cannot be reproduced locally), or an action Glotto itself refuses. When that verdict depends on a server URL or an example, the message says it cannot be judged locally instead of predicting what glotto generate will do. An action whose target matches nothing is the common case. The Overlay standard skips such an action, but Glotto refuses it, so glotto generate fails until you fix or remove it. When every transform applies, the block already describes the post-transform surface and this warning does not appear. |
GLOTTO_MIGRATE_SPEAKEASY_SOURCE_AMBIGUOUS |
error | Your workflow declares several sources and glotto.yml carries exactly one. No file is written. The message says which of the two real shapes you have: several genuinely different documents (migrate each separately), or one document under per-language overlay stacks (pick the overlay stack you want as the baseline). Re-run with --source <id>. |
GLOTTO_MIGRATE_SPEAKEASY_SOURCE_AMBIGUOUS stops the migration and writes nothing on purpose.
Picking a source for you would regenerate your SDKs from a document you did not choose — and
because the output still matches that input, no later check could notice. It surfaces when your
own users call a method that is not there.