У мене локально працює: що це, чому відбувається та як запобігти

Автор: IT Sectr Опубліковано: 2026-07-30 Час читання: 8 хв

«Works on my machine» — a classic phrase uttered by a developer who cannot reproduce a bug in their local environment, even though the bug consistently appears for other team members or in production. The situation arises due to differences in configuration, dependency versions, operating system, or data between the developer’s machine and the environment where the bug occurs. According to the Stack Overflow Survey 2023, 58% of developers say this phrase at least once a month, and 31% — weekly. Let’s explore why code does not behave the same everywhere and how to standardize the environment.

Key Takeaways

  • «Works on my machine» — a meme and a real problem indicating environment discrepancies within a team
  • Main causes: different dependency versions, environment variables, OS, and regional settings
  • The problem is solved by standardizing the environment via Docker or Vagrant
  • Lock files (package-lock, Podfile.lock) pin dependency versions for all developers
  • Regular sync with the repository and clean dependency installation reduce the frequency of the issue

What Does «Works on My Machine» Mean

«Works on my machine» — a phrase uttered by a developer when a colleague or tester reports a bug, but the bug does not reproduce on the developer’s machine. Outwardly, it looks like denial of the problem, but technically the situation is real: code can indeed work in one environment and fail in another. A single bit of configuration difference can change application behavior drastically.

The phrase has become a meme in the IT community because it is both truthful and useless. From the developer’s perspective, the code really does work on their machine. From the team’s perspective, the problem exists and needs to be solved, not excused. The humor lies in the fact that the developer is telling the truth, but that truth does not help fix the bug. The meme is so popular that thousands of posts on Reddit, XKCD, and DevOps conferences are dedicated to it.

From a process standpoint, the phrase «works on my machine» is an indicator of environment reproducibility problems. If two developers cannot get the same result from the same code, the environment setup process is not standardized. DevOps practice states: the environment must be reproducible with a single command from the repository, without manual steps.

Why the Local Environment Differs from Production

A developer’s local environment almost always differs from production. The developer uses macOS or Windows, while the server runs on Linux. Different operating systems have different file systems, encodings, thread timings, and system calls. Even if both environments are Linux, the kernel version, glibc, and OpenSSL may differ.

The second reason is the set of installed software. The developer’s machine may have a global installation of Node.js 20, while the CI/CD configuration specifies version 18. Or the developer uses PostgreSQL 16 locally, while production runs PostgreSQL 14. Differences in minor versions are often unnoticeable, but major updates can change SQL query behavior. According to npm Inc., 67% of dependency-related bugs are caused by patch version differences.

The third reason is network conditions. The local machine has no latency, bandwidth limits, or DNS issues. In production, any request to an external API can take 500 ms instead of 5 ms. Timeouts, retry logic, race conditions — all these problems only manifest under real load and real network conditions. Network emulation through tools like Toxiproxy helps identify such issues before deployment.

Typical Causes of Bug Non-Reproducibility Locally

The first cause is missing data. The developer works with test fixtures, while production has millions of records with unexpected values. NULL in a field the developer assumed required, Unicode characters in a name, strings that are too long — all of these can cause bugs that are irreproducible on a local database with synthetic data.

The second cause is different compilation and build flags. A release (Distribution) build may differ from a debug build. Compiler optimizations, removal of debug logs, function inlining — all of these can hide or, conversely, trigger bugs. A typical example: an assert works in the debug build but fails in the release build due to a different variable initialization order.

The third cause is local cache and temporary files. A developer might not notice a bug because old scripts are cached in the browser, outdated data persists in Redis, or temporary files from previous runs remain in the file system. A clean run (incognito mode, cache clearing, fresh install) often reproduces the bug that did not show up «on its own.»

The fourth cause is conflicts between global and local dependencies. Tools like Ruby gems, Python pip, and Node.js npm can have globally installed packages that «help» the code work locally but are absent in production. Using virtual environments (virtualenv, venv, nvm) isolates the project from global installations and makes the environment reproducible.

Impact on Teamwork and Trust

The phrase «works on my machine» erodes trust within the team. If a developer regularly cannot reproduce bugs, colleagues begin to doubt their competence or thoroughness. Over time, this leads to micromanagement: every change requires verification by a second developer, slowing down development. According to Google Project Aristotle, psychological safety in a team directly affects productivity, and constant arguments about the environment are one of the factors that reduce it.

The second problem is slower code review. If a developer cannot reproduce a bug locally, they may reject a colleague’s pull request with the words «it works for me — so the problem is on your end.» This provokes conflicts and delays feature delivery. Standardizing the environment removes this conflict: if both developers work in the same Docker container, the question of «who has it working» loses its meaning.

The third problem is lost bugs in the tracker. Bugs that «cannot be reproduced by the developer» are often closed with a «Cannot Reproduce» label. A month later, the bug resurfaces in production, and fixing it costs 10 times more. The rule: if a bug reproduces for at least one person, it exists regardless of whether it works on the developer’s machine or not.

How to Standardize the Developer Environment

The first and most effective method is Docker. The entire project should be runnable with docker-compose up without any additional steps. The database, cache, message queue, web server — everything spins up in containers. The developer only needs to install Docker and Git. Everything else runs inside containers. This guarantees that all team members have the same environment regardless of their OS.

The second method is version managers. If Docker is not possible (licensing restrictions, legacy infrastructure), use nvm (Node.js), rbenv (Ruby), pyenv (Python), sdkman (Java). Version managers allow switching language and tool versions per project. Files like .nvmrc, .ruby-version, .python-version should be in the repository and checked by CI/CD.

The third method is Vagrant for virtual machines. Vagrant spins up a virtual machine with a specified OS and configuration on top of VirtualBox or VMware. All dependencies are installed inside the VM via provisioning scripts (shell, Ansible, Puppet). Vagrant is heavier than Docker but provides full OS-level isolation — useful for projects that depend on a specific Linux kernel version.

The fourth method is Makefile and bootstrap scripts. Even a simple Makefile with install, test, build, and clean targets can standardize routine tasks. The make install command should install all dependencies, set up the database, and create test data. A single entry point for all developers eliminates manual errors during environment setup.

Tools for Preventing Environment Drift

The primary tool is lock files for dependencies. package-lock.json (npm), yarn.lock (Yarn), Podfile.lock (CocoaPods), pubspec.lock (Flutter) pin exact versions of every package. Without a lock file, two developers installing dependencies at different times may get different minor versions. The lock file must be in the repository and not edited manually.

The second tool is .env.example in the repository. A template file for environment variables with comments. The developer copies it to .env and fills in their values. The CI/CD pipeline checks that all required variables are set. According to GitLab 2023, teams using .env.example reduce environment variable-related incidents by 40%.

The third tool is pre-commit hooks. Automated checks that run before every commit: linter, formatter, type checking, tests. If hooks are configured identically for all developers, formatting or type errors that «passed locally» will not reach production. Husky for JavaScript and pre-commit for Python are popular solutions.

The fourth tool is a CI/CD pipeline that runs tests in a clean environment. If tests pass in CI but fail locally, the issue is in the local environment setup. If tests fail in CI, the pull request is not merged. This hard rule prevents bugs that «work locally» from reaching the main branch.

Frequently Asked Questions

Why do developers often say «it works for me» instead of immediately looking for the cause?

This is a defense reaction: the developer spends a lot of time debugging, and hearing that the code does not work is psychologically painful. The phrase gives them time to «switch gears» and start looking for the cause without feeling guilty.

How should I respond if a developer says «it works on my machine»?

Ask them to reproduce the bug in a clean environment (clean install, incognito mode). If it does not reproduce, compare dependency versions and environment variables. If that doesn’t help, spin up a Docker environment identical to production.

How does Docker solve the «Works on my machine» problem?

Docker provides an isolated container with a fixed configuration that runs identically on any OS. All developers use the same Dockerfile, so the environment is identical. If a bug does not reproduce in the container, then the problem is indeed in the code, not the system.

How do lock files help prevent discrepancies?

A lock file pins the exact hashes and versions of all transitive dependencies. Even if a new version of a dependency is published in the registry, installing from the lock file guarantees that every developer gets the same set of packages as everyone else.

Should I use virtual machines instead of Docker?

Vagrant with VirtualBox is justified if the project depends on specific OS kernel modules or requires full kernel-level isolation. For 90% of projects, Docker is lighter, faster, and more convenient. The choice depends on how deeply the project interacts with the OS.

Summary

  • «Works on my machine» is not an excuse but a symptom of environment discrepancies within the team
  • Main causes: different versions of dependencies and tools, environment variables, OS, and data
  • The phrase erodes trust within the team and slows down code review and feature delivery
  • Docker is the primary tool for standardizing the environment for all developers
  • Lock files and .env.example pin configuration in the repository
  • Pre-commit hooks and CI/CD pipeline automatically verify code in a clean environment
  • A standardized environment saves hours of debugging and eliminates «magical» bugs

Ми розробимо мобільний застосунок під ключ

IT Sectr створює застосунки для iOS та Android для стартапів і бізнесу з 2017 року. Ми проконсультуємо вас і запропонуємо найкраще рішення.

Обговорити проект

Читайте також