What a Migration Does to Your Fine-Tuning Artifacts
9 min read · updated August 11, 2026
You change the base URL and the key, leave the model string alone, and get a 404 saying the model does not exist. That error is correct and it is telling you something structural about what you own.
The 404 that starts this
A completed OpenAI fine-tuning job yields a model identifier in the shape ft:gpt-4.1-nano-2025-04-14:openai::BTz2REMH — base model, organisation, optional suffix, job-specific identifier — documented in OpenAI’s supervised fine-tuning guide. That string is not a description of a model. It is a primary key into one provider’s serving infrastructure, and it is meaningless anywhere else. Sent to a different provider it produces the same not-found error any nonsense model string would; sent to the same provider from a different organisation it produces a permission error instead, which is a more informative failure because it tells you the artifact exists and is simply not yours to call.
The instinct at this point is to look for an export. There generally is not one. OpenAI’s fine-tuning documentation describes accessing fine-tuned models by ID through the API and makes no provision for downloading weights; the same is true of the managed fine-tuning offerings on the major clouds, where the trained artifact stays inside the platform that trained it. The reason is not primarily commercial — it is that the base weights are not yours to redistribute, and a full fine-tune is derived from them.
Four artifacts, one of them portable
A fine-tuning job produces four things, and it is worth listing them separately because people say “our fine-tune” meaning all four at once.
- The training and validation datasets. Yours. Portable in principle, subject to reformatting. This is the asset.
- The hyperparameters — epochs, learning-rate multiplier, batch size. Yours in the sense that you chose them, but they were chosen against a specific base model and a specific trainer. They transfer as a starting guess and nothing more.
- The checkpoint reference. Not portable. See below.
- The evaluation baseline — the scores the fine-tuned model achieved on your own held-out set. Portable, and much more valuable than teams treat it, because it is the only thing that tells you whether the rebuild succeeded.
If you carry nothing else across, carry the dataset and the evaluation baseline. The baseline in particular: without it, the retrained model on the new provider is a model with no reference point, and every judgement about it becomes an argument about vibes rather than a comparison against a number you already have.
What a checkpoint reference actually is
OpenAI exposes intermediate checkpoints from a fine-tuning job — the documentation describes querying a checkpoints endpoint with the job ID to list them, with checkpoints automatically retained for the last epochs of the job. It is easy to read the word “checkpoint” and picture a file. What the API returns is an object containing a fine_tuned_model_checkpoint field, and the value of that field is another model identifier of the same ft: shape, plus the metrics recorded at that point in training.
So a checkpoint is a second handle on the same remote artifact, useful for picking an earlier epoch when the final one overfit, and useless for moving anywhere. The metrics attached to it are worth exporting before you decommission the account, because the per-epoch training and validation loss curve is exactly what tells you how many epochs to try first on the new provider — the one place the old hyperparameters carry real information.
Carrying the dataset across
The dataset is portable but not byte-portable. OpenAI’s supervised fine-tuning format is JSONL where each line is an object with a messages array, optionally accompanied by tools and parallel_tool_calls when you are training tool-calling behaviour. Other providers wrap the same conversation in a different envelope, put the system instruction in a separate top-level field rather than as a message with a system role, and name the roles differently. The conversion is mechanical, which makes it tempting to do with a one-off script and never look at again. Three things are worth checking after the conversion rather than before:
- Where the system instruction landed. If the source format carried it as the first message and the target format has a dedicated field, a naive converter will either drop it or leave it as a user turn. Both silently change what you are training.
- Tool-call examples. Assistant turns containing tool calls have the most format-specific shape in the file, and a converter written against text-only examples will mangle them. Count them before and after.
- Token budget per example. The new provider’s tokenizer counts your examples differently, so examples that fitted under the old per-example limit may not fit under the new one. This is the same mechanism described in the tokenizer language tax, and it bites hardest on non-English data.
The format details themselves belong on the fine-tune data format page; what matters here is that the conversion is the migration, and the conversion is the step where the training signal quietly degrades.
The open-weights case is different, but not free
If you trained an adapter — LoRA or similar — on open weights, you genuinely do hold a file, typically tens or hundreds of megabytes rather than the full model. That file is portable in a way a hosted fine-tune is not, but it carries two hard dependencies. It is bound to the exact base checkpoint it was trained against, so applying it to a different revision of nominally the same model produces degraded output rather than an error. And it is bound to a serving runtime that can load adapters at all; a provider that serves only its own catalogue cannot host it, whatever the licence says.
The honest summary is that portability of fine-tuning artifacts is a property of the deployment model, not of the licence. Hosted fine-tunes are rebuilt from the dataset. Adapters move between runtimes that support them, pinned to a base checkpoint. In both cases the plan that works is the same: keep the dataset and the evaluation baseline under your own version control, and treat the trained model as a cache you can regenerate rather than a thing you own.