<!-- mobian-agent-page publisher="dailydev" canonical="https://daily.dev/posts/upgrading-mlflow-pipelines-across-a-python-version-boundary-kondfmwbj" -->

---
title: Upgrading MLflow Pipelines Across a Python Version Boundary
description: Upgrading Databricks Runtime from 14.3 (Python 3.10) to 17.3 (Python 3.12) broke MLflow model loading with a cryptic 'TypeError: code() argument 13 must be...
canonical: https://daily.dev/posts/upgrading-mlflow-pipelines-across-a-python-version-boundary-kondfmwbj
twitter:card: summary_large_image
twitter:site: @dailydotdev
og:type: website
og:site_name: daily.dev
og:title: Upgrading MLflow Pipelines Across a Python Version Boundary | daily.dev
og:description: Upgrading Databricks Runtime from 14.3 (Python 3.10) to 17.3 (Python 3.12) broke MLflow model loading with a cryptic 'TypeError: code() argument 13 must be...
og:url: https://daily.dev/posts/upgrading-mlflow-pipelines-across-a-python-version-boundary-kondfmwbj
og:image: https://api.daily.dev/og/posts/KondfMWbj.png
og:image:alt: Upgrading MLflow Pipelines Across a Python Version Boundary
og:image:width: 1200
og:image:height: 630
og:locale: en
---

> ## Documentation Index
> Fetch the complete documentation index at: https://daily.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Upgrading MLflow Pipelines Across a Python Version Boundary

**[Zalando](https://daily.dev/sources/zalando)** · 7 min read · 0 upvotes · 0 comments

## Summary

Upgrading Databricks Runtime from 14.3 (Python 3.10) to 17.3 (Python 3.12) broke MLflow model loading with a cryptic 'TypeError: code() argument 13 must be str, not int'. The cause: cloudpickle embeds Python bytecode into serialized model artifacts, and bytecode changed between 3.10 and 3.12. Retraining was too costly given multiple TB of training data across five model types per category, so the team built a 'Load and Repack' strategy: load old models in a DBR 14.3 environment, strip the pyfunc wrapper, then relog a new pure-Python wrapper under Python 3.12 using uv for dependencies. Going forward they plan to drop pickle entirely using native formats like CatBoost's .cbm, PyTorch's pt2 export, and sklearn's skops, plus MLflow's 'Models from Code' pattern.

## Full article

daily.dev links to this article rather than hosting it. Read it at the original source: <https://engineering.zalando.com/posts/2026/10/upgrading-mlflow-pipelines.html>

## Questions this post answers

### Why does loading an old MLflow model fail with 'TypeError: code() argument 13 must be str, not int' after upgrading Python?

This error occurs because cloudpickle embeds Python bytecode and version metadata directly into serialized model artifacts, and bytecode structures changed significantly between Python 3.10 and 3.12. When a newer interpreter tries to unpickle a model logged under the older Python version, it cannot safely parse the embedded bytecode, raising this TypeError during model loading from the MLflow registry.

_Developers tracking Python version breakages like this one follow MLflow and Databricks updates on daily.dev._

### How can I migrate production MLflow models to a new Python version without retraining them?

Use a 'Load and Repack' strategy: spin up a temporary environment matching the old Python version and library set, load the cloudpickle-serialized models there, and separate the raw model weights from their pyfunc wrapper. Then wrap the extracted weights in a new, streamlined pure-Python wrapper class and relog them to MLflow under the new Python version, promoting the result back to the production alias.

_Teams planning a Python upgrade without costly retraining can follow ML pipeline migration strategies on daily.dev._

### How do I avoid cloudpickle version compatibility issues when logging models with MLflow?

Use MLflow's native serialization flavors instead of wrapping models with cloudpickle: mlflow.catboost.log_model() saves directly to CatBoost's native .cbm format, mlflow.pytorch.log_model with serialization_format='pt2' uses torch.export.save (needs PyTorch 2.4 or higher), and mlflow.sklearn.log_model with serialization_format='skops' secures scikit-learn models natively, avoiding embedded Python bytecode entirely.

_Anyone future-proofing ML artifacts against runtime upgrades can track MLflow serialization patterns on daily.dev._

## Similar posts on daily.dev

- [Pickle in the Middle – Hijacking Vertex AI Model Uploads for Cross-Tenant RCE](https://daily.dev/posts/pickle-in-the-middle-hijacking-vertex-ai-model-uploads-for-cross-tenant-rce-cuz0rz1po) · Unit 42 · 0 upvotes · 0 comments
- [Parity before cutover](https://daily.dev/posts/parity-before-cutover-o9ipdziob) · Programming Digest · 5 upvotes · 1 comments
- [EVE Online Departs for Python 3](https://daily.dev/posts/eve-online-departs-for-python-3-a2pvhs0kj) · Planet Python · 0 upvotes · 0 comments
- [In a pickle: Why every pickle defense in machine learning is bypassed the same way](https://daily.dev/posts/in-a-pickle-why-every-pickle-defense-in-machine-learning-is-bypassed-the-same-way-xvaxd2p7n) · Sysdig Blog · 0 upvotes · 0 comments

---

Tags: [#machine-learning](https://daily.dev/tags/machine-learning), [#python](https://daily.dev/tags/python), [#databricks](https://daily.dev/tags/databricks)

[View this post on daily.dev](https://daily.dev/posts/upgrading-mlflow-pipelines-across-a-python-version-boundary-kondfmwbj)

```json
{"@context":"https://schema.org","@graph":[{"@type":"Organization","@id":"https://daily.dev/#organization","name":"daily.dev","url":"https://daily.dev","logo":{"@type":"ImageObject","url":"https://daily.dev/apple-touch-icon.png","width":180,"height":180},"sameAs":["https://twitter.com/dailydotdev","https://github.com/dailydotdev","https://www.linkedin.com/company/daily-dev-ltd"]},{"@type":"WebSite","@id":"https://daily.dev/#website","url":"https://daily.dev","name":"daily.dev","publisher":{"@id":"https://daily.dev/#organization"},"potentialAction":{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https://daily.dev/search?q={search_term_string}"},"query-input":"required name=search_term_string"}}]}
{"@context":"https://schema.org","@type":"TechArticle","headline":"Upgrading MLflow Pipelines Across a Python Version Boundary","url":"https://daily.dev/posts/upgrading-mlflow-pipelines-across-a-python-version-boundary-kondfmwbj","mainEntityOfPage":{"@type":"WebPage","@id":"https://daily.dev/posts/upgrading-mlflow-pipelines-across-a-python-version-boundary-kondfmwbj"},"datePublished":"2026-10-30T23:40:06.911Z","dateModified":"2026-10-30T23:40:37.556Z","description":"Upgrading Databricks Runtime from 14.3 (Python 3.10) to 17.3 (Python 3.12) broke MLflow model loading with a cryptic 'TypeError: code() argument 13 must be...","image":"https://media.daily.dev/image/upload/f_auto,q_auto/v1/posts/05222ea5bf86b8ef59ae2ab56aefcbd2?_a=AQAEuop","thumbnailUrl":"https://media.daily.dev/image/upload/f_auto,q_auto/v1/posts/05222ea5bf86b8ef59ae2ab56aefcbd2?_a=AQAEuop","isAccessibleForFree":true,"articleSection":"Zalando","inLanguage":"en","publisher":{"@type":"Organization","name":"daily.dev","url":"https://daily.dev","logo":{"@type":"ImageObject","url":"https://daily.dev/apple-touch-icon.png","width":180,"height":180}},"author":{"@type":"Organization","name":"Zalando","logo":"https://media.daily.dev/image/upload/t_logo,f_auto/v1/logos/94640378400546638ce8f6311afa73e3","url":"https://daily.dev/sources/zalando"},"commentCount":0,"discussionUrl":"https://daily.dev/posts/upgrading-mlflow-pipelines-across-a-python-version-boundary-kondfmwbj","interactionStatistic":[{"@type":"InteractionCounter","interactionType":{"@type":"LikeAction"},"userInteractionCount":0},{"@type":"InteractionCounter","interactionType":{"@type":"CommentAction"},"userInteractionCount":0}],"keywords":"machine-learning,python,databricks","timeRequired":"PT7M"}
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https://daily.dev"},{"@type":"ListItem","position":2,"name":"Zalando","item":"https://daily.dev/sources/zalando"},{"@type":"ListItem","position":3,"name":"Upgrading MLflow Pipelines Across a Python Version Boundary"}]}
{"@context":"https://schema.org","@type":"FAQPage","@id":"https://daily.dev/posts/upgrading-mlflow-pipelines-across-a-python-version-boundary-kondfmwbj#faq","mainEntity":[{"@type":"Question","name":"Why does loading an old MLflow model fail with 'TypeError: code() argument 13 must be str, not int' after upgrading Python?","acceptedAnswer":{"@type":"Answer","text":"This error occurs because cloudpickle embeds Python bytecode and version metadata directly into serialized model artifacts, and bytecode structures changed significantly between Python 3.10 and 3.12. When a newer interpreter tries to unpickle a model logged under the older Python version, it cannot safely parse the embedded bytecode, raising this TypeError during model loading from the MLflow registry. Developers tracking Python version breakages like this one follow MLflow and Databricks updates on daily.dev."}},{"@type":"Question","name":"How can I migrate production MLflow models to a new Python version without retraining them?","acceptedAnswer":{"@type":"Answer","text":"Use a 'Load and Repack' strategy: spin up a temporary environment matching the old Python version and library set, load the cloudpickle-serialized models there, and separate the raw model weights from their pyfunc wrapper. Then wrap the extracted weights in a new, streamlined pure-Python wrapper class and relog them to MLflow under the new Python version, promoting the result back to the production alias. Teams planning a Python upgrade without costly retraining can follow ML pipeline migration strategies on daily.dev."}},{"@type":"Question","name":"How do I avoid cloudpickle version compatibility issues when logging models with MLflow?","acceptedAnswer":{"@type":"Answer","text":"Use MLflow's native serialization flavors instead of wrapping models with cloudpickle: mlflow.catboost.log_model() saves directly to CatBoost's native .cbm format, mlflow.pytorch.log_model with serialization_format='pt2' uses torch.export.save (needs PyTorch 2.4 or higher), and mlflow.sklearn.log_model with serialization_format='skops' secures scikit-learn models natively, avoiding embedded Python bytecode entirely. Anyone future-proofing ML artifacts against runtime upgrades can track MLflow serialization patterns on daily.dev."}}]}
```

