The Mercury Puzzle

Le Verrier’s Mercury anomaly, the Vulcan hypothesis, and the road to general relativity.
Author

Jonathan Whitmore

Published

April 9, 2026

The Same Method, a Different Outcome

Fresh from the triumph of Neptune, Le Verrier turned his perturbation methods to the entire solar system. By 1859, he had completed an exhaustive analysis of Mercury’s orbit and found something troubling: after accounting for every known planet’s gravitational pull, Mercury’s perihelion — the closest point to the Sun in its orbit — was advancing faster than it should.

The Anomalous Precession

Mercury’s perihelion precesses (rotates slowly around the Sun) due to gravitational tugs from Venus, Earth, and Jupiter. Le Verrier computed this classical precession and compared it to observations. The discrepancy was small but definite.

Code
from discoverneptune.historical_values import (
    LEVERRIER_MERCURY_1859,
    NEWCOMB_MERCURY_1882,
    MODERN_MERCURY_ANOMALY,
)

print("Mercury's anomalous perihelion precession — historical progression:")
print(f"  Le Verrier (1859):  {LEVERRIER_MERCURY_1859.anomaly_arcsec_per_century:.1f} arcsec/century")
print(f"  Newcomb (1882):     {NEWCOMB_MERCURY_1882.anomaly_arcsec_per_century:.2f} arcsec/century")
print(f"  Modern value:       {MODERN_MERCURY_ANOMALY.anomaly_arcsec_per_century:.2f} arcsec/century")
Mercury's anomalous perihelion precession — historical progression:
  Le Verrier (1859):  38.0 arcsec/century
  Newcomb (1882):     42.95 arcsec/century
  Modern value:       42.98 arcsec/century

Note that Le Verrier’s original 1859 value was about 38 arcsec/century — the familiar “43 arcsec/century” came from Simon Newcomb’s refined analysis in 1882 using better observational data. The anomaly was real; the precise number took decades to pin down.

Reproducing the Anomaly

We can reproduce this with a 500-year REBOUND integration. First, a Newtonian simulation (Sun + Mercury + Venus + Earth + Jupiter + Saturn), then the same system with general-relativistic corrections via reboundx.

Code
from pathlib import Path
import pandas as pd
from discoverneptune.mercury import (
    analytical_gr_precession,
    perihelion_precession_rates,
)
from discoverneptune.simulation import StateVector

# Load bundled J2000 state vectors for inner planets
from discoverneptune.data import find_bundled_data_dir

data_dir = find_bundled_data_dir()

inner_svs = pd.read_csv(data_dir / "inner_planet_state_vectors_j2000.csv")
inner_state = {
    row.planet: StateVector(row.x, row.y, row.z, row.vx, row.vy, row.vz)
    for row in inner_svs.itertuples(index=False)
}

mercury_sv = inner_state["mercury"]
venus_sv = inner_state["venus"]
earth_sv = inner_state["earth"]
jupiter_sv = inner_state["jupiter"]
saturn_sv = inner_state["saturn"]
Code
rates = perihelion_precession_rates(
    mercury_sv, venus_sv, earth_sv, jupiter_sv,
    saturn_sv=saturn_sv,
)

print(f"Newtonian precession rate:  {rates.newtonian_arcsec_per_century:.1f} arcsec/century")
print(f"GR-corrected rate:          {rates.gr_corrected_arcsec_per_century:.1f} arcsec/century")
print(f"GR contribution (sim):      {rates.gr_contribution_arcsec_per_century:.1f} arcsec/century")
print(f"GR contribution (formula):  {analytical_gr_precession():.1f} arcsec/century")
Newtonian precession rate:  524.7 arcsec/century
GR-corrected rate:          567.6 arcsec/century
GR contribution (sim):      43.0 arcsec/century
GR contribution (formula):  43.0 arcsec/century

The GR contribution matches Einstein’s textbook formula to within 0.1 arcsec/century. This is the anomaly Le Verrier found — but he didn’t know what caused it.

The Vulcan Hypothesis

Le Verrier’s method had worked brilliantly for Neptune: an unexplained orbital anomaly → predict a new planet → find it. He applied the same logic to Mercury and predicted an inner planet he called Vulcan, orbiting between Mercury and the Sun. Telescopic searches and solar-transit observations continued through the 1870s before the hypothesis was abandoned.

Code
from discoverneptune.mercury import vulcan_mass_estimate
import numpy as np

print(f"{'Distance (AU)':>14}  {'Required mass (Earth masses)':>28}")
print("-" * 46)
M_EARTH = 1.0 / 332_946.0
for a_v in [0.10, 0.15, 0.20, 0.25]:
    m = vulcan_mass_estimate(a_v) / M_EARTH
    print(f"{a_v:>14.2f}  {m:>28.2f}")

print()
print("Any planet massive enough would be visible during solar transits.")
print("Vulcan was never found.")
 Distance (AU)  Required mass (Earth masses)
----------------------------------------------
          0.10                          0.53
          0.15                          0.24
          0.20                          0.13
          0.25                          0.09

Any planet massive enough would be visible during solar transits.
Vulcan was never found.

Three Values, One Story

Code
import matplotlib.pyplot as plt

labels = ["Le Verrier\n(1859)", "Newcomb\n(1882)", "Modern\nvalue", "Our simulation\n(GR contrib)"]
values = [
    LEVERRIER_MERCURY_1859.anomaly_arcsec_per_century,
    NEWCOMB_MERCURY_1882.anomaly_arcsec_per_century,
    MODERN_MERCURY_ANOMALY.anomaly_arcsec_per_century,
    rates.gr_contribution_arcsec_per_century,
]

def _build(theme="light"):
    apply_style(theme)
    pal = palette(theme)
    cycle = category_cycle(theme)
    bar_colors = [cycle[0], cycle[0], cycle[1], cycle[2]]
    fig, ax = plt.subplots(figsize=fig_size("wide"))
    ax.barh(labels, values, color=bar_colors)
    ax.set_xlabel("Anomalous precession (arcsec/century)")
    ax.set_title("Mercury's perihelion anomaly — from Le Verrier to GR")
    truth_line(ax, 42.98, label="Einstein's formula: 42.98", axis="x", theme=theme)
    return fig

display(dual_render(_build, alt="Mercury perihelion anomaly values from Le Verrier 1859 to modern GR, with Einstein formula reference line"))
Figure 1: The Mercury anomaly value as measured by three generations of astronomers, and our simulation’s GR contribution.

Why Neptune Worked and Vulcan Didn’t

The same inverse method — the same mathematician — produced a triumph and a failure. The difference is physics, not methodology:

  • At 19+ AU (Neptune’s orbit), GR corrections are ~0.01 arcsec/century — five orders of magnitude below the noise floor. Any anomaly must come from matter.
  • At 0.39 AU (Mercury’s orbit), spacetime curvature is strong enough to produce 43 arcsec/century of precession with no matter at all.

Le Verrier’s Newtonian framework was the best available. Its failure at Mercury wasn’t a mistake — it was a signpost pointing toward a deeper theory that wouldn’t arrive for another 56 years.

References

  • Le Verrier, U. “Théorie du mouvement de Mercure.” Comptes Rendus 49 (1859).
  • Newcomb, S. “Discussion of the Transits of Mercury.” Astronomical Papers 1 (1882).
  • Einstein, A. “Erklärung der Perihelbewegung des Merkur aus der allgemeinen Relativitätstheorie.” Sitzungsberichte der Preußischen Akademie der Wissenschaften (1915).
  • Lequeux, J. Le Verrier: Magnificent and Detestable Astronomer (2013), chapter 10.