Jagannatha Hora Moola Dasa Bug: The Moolatrikona 12-Year Error

JHora Reverse Engineered — From Binary to Browser
Part 3 examines a recovered Moola Dasa period rule and compares it with the printed text it is supposed to implement.

Jagannatha Hora has been the reference desktop program for Jaimini and Udu dasas for two decades. Its source code has never been published. That is not an incidental detail about how the program is distributed — it is the entire problem.

A closed calculator is an authority you cannot audit. When it prints a dasa period, nothing in the output says which rule produced it, which text that rule came from, or whether the arithmetic was checked against anything at all. The number simply appears, in the same font, with the same confidence, as every correct number the program has ever produced.

Over the last year we disassembled that executable, inventoried its 7,535 functions, and rebuilt the calculations it performs as readable code. We did this so that the program could be compared with the books it claims to follow. And when we compared the Moola Dasa period rule with the rule Sanjay Rath prints in Vimsottari & Udu Dasas, they disagreed.

Not by a rounding error. By twelve years.

Short version. In Moola Dasa, a planet that occupies its own Moolatrikona sign is zero signs away from it, not twelve. The printed rule subtracts nothing from its allotment; the recovered rule subtracts a full revolution.

The recovered JHora routine overwrites that zero with 12. Saturn in Aquarius therefore receives 7 years where the printed rule gives 19. Because the second cycle is the complement, the missing years do not vanish; they push every intervening boundary twelve years early, across a window that in a typical chart covers most of adult life.

Why a closed-source calculator is a single point of failure

Vedic astrology is unusually dependent on software. Nobody computes a Vimshottari sequence on paper for a consultation; the dasa table is copied from a program into a reading. That makes a small number of closed programs the de facto standard of the practice, and it makes their arithmetic a piece of shared infrastructure that nobody can inspect.

The usual defence is that the programs are "based on" a well-known text. But "based on" is not a specification. It leaves open precisely the questions that matter: which text, which edition, which reading of an ambiguous verse, and what the program does when the text is silent. A closed program cannot answer those questions, because there is nothing to look at except the output — and the output is only ever the answer, never the working.

This article is what the working looks like once you can see it.

What Moola Dasa is, and why one bad period matters

Moola Dasa — also called Lagna Kendradi Graha Dasa, and traced by Rath to the Saravali of Kalyan Verma — is the dasa of past karma. It is not a nakshatra system. It is a planetary system built from the strength of signs: the dasa begins with the strongest occupied quadrant, then the panaphara or apoklima planets depending on the parity of the Lagna, and proceeds through all nine planets.

It is a flat sequence of eighteen major periods — two cycles of the nine planets — not a nested tree. The first cycle's total is normally well under 120 years; the second cycle supplies each planet's complement, so that the two together return to the full Vimshottari allotment of 120.

Rath's motivation for publishing the system was a single historical puzzle, and it is worth quoting because it establishes what the periods are for:

"For example everyone has wondered as to how Bhagavan Sri Rama Chandra was banished to the forest in the beginning of Saturn dasa when the Moon was in Cancer at the time of His birth … Then again the scriptures say that this period of Vanvas (forest dwelling) was for 14 years. This is grossly different from the well known period of 19 years for Saturn dasa. Moola dasa gives the vital clues."

Sanjay Rath, Vimsottari & Udu Dasas, §6.2.1

Read that again with the bug in hand. The book's own worked example turns on Saturn's 19-year Vimshottari allotment being reduced to 14. That reduction is the whole point of the system. A rule that can silently turn nineteen into seven is not a detail; it is a different chart.

The rule as printed

Rath states the period rule in four numbered pieces. The first is the one under test here:

"Rule-1: Count the number of signs from there to its Moolatrikona sign and subtract the number arrived at by 1. This period is to be subtracted from the number of Vimsottari Dasa years assigned to the planet. The net result arrived at indicates the number of years of Moola Dasa/Lagna Kendradi Graha Dasa assigned to the planet."

"Rider 1: Add one year to the final sum if the said planet is exalted and subtract one if the planet is in debilitation."

"Rider 2: For the purposes of this Dasa, the count for Rahu & Ketu shall be reckoned to Aquarius and Scorpio respectively as is done in Narayana Dasa."

Sanjay Rath, Vimsottari & Udu Dasas, §6.2.4

Then Rule-2 fixes the degenerate case: if the subtraction leaves exactly zero, the planet takes its full Vimshottari allotment instead. And Rule-3 fixes the second cycle: each planet's second period is its Vimshottari allotment minus its first, in the same order.

The method is easiest to see in Rath's own worked table, which is laid out in five columns — the allotment B, the raw count C, the count-minus-one D = C − 1, the dignity adjustment E, the net reduction F = D + E, and finally G = B − F. For Jupiter in Cancer, count Cancer to Sagittarius is six, so D = 5; Jupiter is exalted, so E = +1 and F = 6; the allotment is sixteen, so the Moola period is 10.

Note what that table also settles: whether Rider 1 adjusts the reduction or the final result. The prose says "the final sum", but the table adjusts the reduction, and the published Sri Rama durations only work out if it is the reduction. For Jupiter, adjusting the result would give 12 years, not the 10 printed in the book. The table wins, and every number in this article uses the table's reading.

The case the table never tests

Now ask the question the worked example does not: what happens when the planet is already in its Moolatrikona sign?

Count from a sign to itself and you get one, not thirteen. Subtract one and you get zero. The reduction is nothing, so the planet keeps its whole allotment. There is no ambiguity here and no artisan's judgement: the rule is arithmetically forced.

This is not an exotic configuration. Any horoscope with the Sun in Leo, the Moon in Taurus, Mars in Aries, Mercury in Virgo, Jupiter in Sagittarius, Venus in Libra, Saturn or Rahu in Aquarius, or Ketu in Scorpio carries at least one planet in this state — and since every planet must sit in some sign, a large share of ordinary charts do.

What the recovered routine actually does

Here is the period routine as we rebuilt it from the executable. The originating code is FUN_00410CD0, supported by FUN_004AB650, FUN_004AB730 and FUN_004AD280; this is our C# port of their combined behaviour.

private static int JHoraRecoveredMoolaFirstPeriod(
    PlanetName planet,
    ZodiacName occupiedSign,
    bool noCorrectionInMoolatrikona)
{
    var baseYears = JHoraMoolaVimshottariYears(planet);
    var distance = JHoraRecoveredMod12(
        JHoraRecoveredSignIndex(JHoraMoolaTrikonaSign(planet)) -
        JHoraRecoveredSignIndex(occupiedSign));

    if (distance == 0) distance = noCorrectionInMoolatrikona ? 0 : 12;    else if (IsJHoraExaltationSign(planet, occupiedSign) && distance < 12) distance++;
    else if (IsJHoraDebilitationSign(planet, occupiedSign) && distance > 0) distance--;

    var years = Math.Abs(baseYears - distance);
    return years == 0 ? baseYears : years;
}

The table of Moolatrikona signs that JHoraMoolaTrikonaSign consults is the ordinary one, with the nodes assigned as Rider 2 requires:

Sun     => Leo          Mars    => Aries        Mercury => Virgo
Jupiter => Sagittarius  Venus   => Libra        Saturn  => Aquarius
Moon    => Taurus       Rahu    => Aquarius     Ketu    => Scorpio

Everything else in the routine is faithful. distance is exactly the count-minus-one that the printed table's column D calls for; the exaltation and debilitation branches adjust the reduction rather than the result, just as the table does; Math.Abs implements the book's instruction to drop a negative sign; and years == 0 ? baseYears : years is Rule-2, correctly applied.

One line of that routine is wrong.

Recovered JHora Moola Dasa first-period routine in C#, with the line 'if (distance == 0) distance = 12' highlighted as the defect
The recovered period routine. Every branch follows the printed table except the one that handles a planet already in its Moolatrikona sign.

Why twelve is not a count

The defect is one assignment, and it is worth being precise about why it is a defect rather than a convention.

distance is computed with a modulo-twelve helper, so for a planet in its own Moolatrikona it is 0. That is correct: the planet is zero signs away from its Moolatrikona. The next line then replaces the correct value with 12.

Twelve and zero are congruent modulo twelve, so the substitution looks harmless — and it would be, if the variable were fed back into another modulo. It is not. It is used two lines later as a plain integer and subtracted, which is where congruence stops helping: 0 subtracts nothing, 12 subtracts a full revolution.

Read as astrology rather than arithmetic, the assignment asserts that a planet sitting in its own Moolatrikona sign is simultaneously at the greatest possible distance from it. That is not a competing convention found in some other text. It is a statement the counting rule cannot make. There is no edition of Rath, of Parasara, or of the Saravali in which the distance from a sign to itself is the maximum.

What makes it worse rather than better is that the routine carries a switch that would disable it. noCorrectionInMoolatrikona turns the twelve back into zero — that is, the recovered routine contains a setting that restores the printed rule, and in the form we recovered it is off, so the twelve applies by default. Whatever the intent, the effect is that two users comparing the same chart can obtain different Moola Dasa sequences without either of them being told that a doctrinal choice has been made on their behalf.

All nine planets, side by side

The consequence depends on the planet, because the wrong reduction is subtracted from each planet's own allotment. Holding each planet in its own Moolatrikona sign, the printed rule and the recovered routine produce:

Planet Moolatrikona Allotment B Reduction F Printed rule G JHora Error
Sun Leo 6 0 6 6 0
Moon Taurus (also exalted) 10 +1 → 1 9 2 −7
Mars Aries 7 0 7 5 −2
Mercury Virgo (also exalted) 17 +1 → 1 16 5 −11
Jupiter Sagittarius 16 0 16 4 −12
Venus Libra 20 0 20 8 −12
Saturn Aquarius 19 0 19 7 −12
Rahu Aquarius 18 0 18 6 −12
Ketu Scorpio 7 0 7 5 −2

Two rows in that table are the reason this bug is so hard to notice by eye. The Sun's row shows no error at all: six minus twelve is negative six, the absolute value restores six, and the arithmetic silently cancels. That is pure coincidence — the Sun's six-year allotment happens to be half of twelve — but it means a chart with the Sun in Leo will show the bug nowhere.

The Moon and Mercury rows are the opposite trap. Both are exalted in the very sign that is their Moolatrikona, so the printed rule applies Rider 1 and reduces by one, while the recovered routine skips the dignity branch entirely and applies the twelve. A reader who notices "Saturn is twelve too short" and tries to correct manually by adding twelve will overshoot the Moon by five years and Mercury by one.

One planet, two timelines

A single wrong period is only half of the damage, because Moola Dasa is a cumulative schedule. Rath's Rule-3 makes each second-cycle period the complement of its first — so if a first-cycle period loses twelve years, the matching second-cycle period gains twelve. The total still comes to 120. Nothing looks wrong in the arithmetic. The calendar simply moves.

To show the size of that movement, take Rath's own Chart 29 — the Sri Rama horoscope whose durations are printed on page 152 — and change exactly one thing: put Saturn in Aquarius instead of Libra. The planet order is deliberately held at the published sequence so that only the period arithmetic is under test.

Planet in sequence Printed rule, 1st cycle JHora, 1st cycle Printed 2nd cycle JHora 2nd cycle
Jupiter101066
Moon101000
Mars3344
Saturn197012
Sun1155
Venus121288
Rahu171711
Ketu3344
Mercury131344
Total88763244

Both columns still sum to 120 across the two cycles, which is exactly why the flaw is invisible to any test that only checks the total. But the ages at which the periods fall are not the same schedule:

Period Printed rule (age) JHora (age) Shift
Saturn, 1st cycle23 – 4223 – 30−12
Sun, 1st cycle42 – 4330 – 31−12
Venus43 – 5531 – 43−12
Rahu55 – 7243 – 60−12
Ketu72 – 7560 – 63−12
Mercury75 – 8863 – 76−12
Saturn, 2nd cycle98 – 9886 – 98re-joins
Sun, 2nd cycle98 – 10398 – 103aligned
Venus, 2nd cycle103 – 111103 – 111aligned

The zero-length "98 – 98" row needs a word of explanation: Rath's Rule-3 keeps a planet's period even when its complement works out to nothing, so Saturn appears twice in the sequence although its second occurrence lasts no time at all. JHora also preserves zero-duration periods, and that is one of the places its reconstruction is entirely faithful.

The Sun's Moola Dasa moves from a man's forty-second year to his thirtieth. Rahu's moves from fifty-five to forty-three. Everything after Saturn's second period snaps back into place, so the damage is not a permanent offset that a reader might eventually spot as a pattern — it is a long middle stretch of life that is internally consistent, correctly ordered, and simply wrong.

Two Moola Dasa timelines for the same chart, the lower one shifted twelve years earlier from Saturn's first period until Saturn's second
The same chart sequence under both rules. Periods before Saturn's first cycle and after Saturn's second are identical; everything between them runs twelve years early.

Why this survived two decades of use

Nothing about this bug is subtle in isolation, so it is worth explaining why it is nonetheless well hidden.

The published worked example cannot expose it

Rath's illustrated chart places Jupiter and Moon in Cancer, Saturn in Libra, Mars in Capricorn, Rahu in Sagittarius, the Sun in Aries, Venus in Pisces, Mercury in Taurus and Ketu in Gemini. Check each against its Moolatrikona sign and not one of the nine is at home. The book's single worked table therefore exercises every branch of the rule except the defective one.

We can confirm this directly: run the recovered routine on Rama's chart and it returns 10, 10, 3, 14, 1, 12, 17, 3, 13 — the exact figures printed on page 152. The bug is not merely absent from the example; the example is a perfect alibi.

The totals still balance

Every sanity check a user is likely to perform on a dasa table passes. The nine periods are all present and in the correct order. The second cycle complements the first. The two cycles sum to 120. Dates are monotonic. A reader who checks what is checkable finds nothing to check.

Some charts do not show it at all

The Sun's row cancels arithmetically, so a chart whose only Moolatrikona placement is the Sun in Leo produces a table identical under both rules. A practitioner who compared one or two charts between programs, as most would, could easily have picked charts that agreed.

Our own tests did not catch it either

This is the uncomfortable part. Our Moola Dasa implementation had a passing test suite, and every test passed because every fixture reproduced a published example — and the published examples are the ones that cannot fail. It was not the tests that found this. It was the decision to read the rule out loud, clause by clause, against the code that claimed to implement it.

How confident are we?

We should be explicit about what this claim rests on, because a public accusation of error deserves the same scrutiny as the error.

The code above is our reconstruction, not JHora's source. What justifies it is that our reconstruction reproduces JHora's published outputs before it diverges from the book: the Sri Rama durations, the sum-to-120 complement rule, the zero-duration second-cycle periods, and the ordering of the nine planets all agree with the program where we can check it. In other words, we did not build a program to disagree with JHora. We built a program that agrees with JHora, and it disagrees with the book in exactly one branch.

The specific constant is a direct binary finding rather than an inference from behaviour: the routine compares the distance to zero and stores twelve, and it does so behind a named option rather than as a computed fallback. That shape is hard to produce by accident in a decompiler.

What we cannot do is run JHora on a chart containing a Moolatrikona placement and show you the printed number, because we do not distribute the program. If you own a copy, this is a five-minute test: cast any chart with Saturn in Aquarius, open the Moola Dasa, and check Saturn's first period. If it reads 19, then our reconstruction of that branch is wrong and this article is wrong with it — tell us and we will publish the correction with the same prominence.

What we changed

Our policy for every recovered routine is now written down and enforced: where the book states a rule, the book wins and the recovered code is deleted; where the book is silent, the recovered rule may be kept but may not present itself as classical, and must either be replaced from a cited text or marked unverified. No name, comment or public field referencing the reverse-engineering survives in the dasa layer.

Applied to Moola, the twelve disappears and the exaltation branch regains the case it was previously masking:

// before: a planet already at its Moolatrikona is pushed a full round out
if (distance == 0) distance = noCorrectionInMoolatrikona ? 0 : 12;

// after: the count is one and the reduction is zero, so the dignity
// rider applies normally, exactly as the printed table does
var reduction = Mod12(SignIndex(MoolatrikonaSign(planet)) - SignIndex(occupiedSign));
if (Exalted(planet, occupiedSign)) reduction++;
else if (Debilitated(planet, occupiedSign)) reduction--;

var years = Math.Abs(baseYears - reduction);
return years == 0 ? baseYears : years;

Saturn in Aquarius now returns 19, Mercury in Virgo returns 16, and the Moon in Taurus returns 9. The change also forced a test to be re-baselined from 7 to 19 — and, because a rule change is worthless without a source attached to it, every one of those expectations now carries its citation in the code.

This is not the only one

Publishing one flaw in detail would be misleading if it implied the rest of the recovered dasa layer were clean. It is not, and we would rather say so than have it discovered later. The conflicts we are currently resolving, each of which needs the same treatment, include:

  • Strongest-seed selection — the recovered candidate set admits Utpanna among the Phalita options, where Rath reserves it for Ayur.
  • Moola period order — the ordering of planets within each sign group uses recovered strength tie-breakers rather than the sequence Rath states.
  • Narayana and Shoola start and duration — both are inherited almost entirely from a recovered sign-comparison cascade rather than from a cited text.
  • Kalachakra — the default method is one of seven recovered variants; six of them have no published source we can point to.
  • Sudarsana — all three tracks share a single antardasa sequence, which is a recovery artefact rather than a documented rule.

None of these is a claim about JHora yet. They are places where our inherited behaviour has no citation, which is a different and more honest thing to say. Each will be taken in turn.

The same method applied to a system that needed no correction is in the companion piece, Vimshottari Janma Dasa: How to Use It & Proof of Accuracy, where the Moon-based dasa is reproduced against Rath's and Raman's own worked charts. Publishing the methods that agree is what makes the one that disagrees credible.

Why we publish this instead of quietly fixing it

There is an obvious objection: a website that offers an alternative implementation has an interest in finding fault with the incumbent. That is a fair objection, and the only real answer is to show the working so completely that the reader can check it without trusting us.

Every step above is reproducible with a copy of the book and a calculator. The count Cancer to Sagittarius is six. The count from a sign to itself is one. Sixteen minus five is eleven, and then plus one is six, and sixteen minus six is ten. If you disagree with a number in this article, you can find it, point at it, and we will correct it in public — which is precisely the process that was unavailable while the calculation lived inside an executable.

That is the real argument here, and it is larger than one bug. A closed astrological program is a claim of authority with nothing behind it that a student can examine. Open calculation is not a licensing preference; it is the difference between a tradition that can correct itself and one that cannot. We would rather publish a fix and be checked than hold a correct answer nobody can verify.

Check your own Moola Dasa

Open the rebuilt Jagannatha Hora in the browser, or read the recovered-code notes and run the numbers yourself. If you find a chart where our figures and yours disagree, send it to us.

Sources

  • Sanjay Rath, Vimsottari & Udu Dasas (Sagar Publications, 2005), §6.2 "Moola Dasa", including §6.2.2 (dasa scheme), §6.2.3 (sequence), §6.2.4 (period: Rules 1–3 and Riders 1–2) and §6.2.5 (the Sri Rama illustration, Chart 29, Steps 1–5).
  • Saravali of Kalyan Verma, cited by Rath as the source of Lagna Kendradi Graha Dasa.
  • Parasara, Brihat Parasara Hora Sastra, ch. 46, shlokas 161–164 — the four rules of sign and planet strength that govern the period order.
  • Our reverse-engineering notes for the executable: the recovered function inventory, the Moola routine at FUN_00410CD0, and the shared sign-strength helpers at FUN_004AB650, FUN_004AB730 and FUN_004AD280.
  • The public source of the reverse-engineered work: github.com/VedAstro.
  • VedAstro's open Moola Dasa calculation, alongside the other eighteen dasa systems: Free Vedic Dasa API, and the API documentation.
A note on scope: this article is about the correctness of a calculation, not about the validity of astrology as a predictive practice. Astrology is a traditional interpretive discipline, not a scientifically validated method. Judge the arithmetic on its sources, and use any chart for reflection and study rather than as a substitute for professional medical, legal, financial or relationship advice.