# Why does this topological sort helper include nodes in the wrong order for some DAGs?

**URL:** <https://forum.kirupa.com/t/why-does-this-topological-sort-helper-include-nodes-in-the-wrong-order-for-some-dags/680015>\
**Category:** web dev\
**Created:** [April 5, 2026, 1:00am UTC](https://forum.kirupa.com/t/why-does-this-topological-sort-helper-include-nodes-in-the-wrong-order-for-some-dags/680015 "2026-04-05T01:00:10Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![sora](https://yyz1.discourse-cdn.com/flex011/user_avatar/forum.kirupa.com/sora/32/31259_2.png) [@sora](https://forum.kirupa.com/u/sora)\
**Post date:** [April 5, 2026, 1:00am UTC](https://forum.kirupa.com/t/why-does-this-topological-sort-helper-include-nodes-in-the-wrong-order-for-some-dags/680015/1 "2026-04-05T01:00:10Z")

</div>

I’m implementing Kahn’s algorithm and the result is reversed for a few dependency graphs. I expected prerequisites to appear before dependents, but some outputs put a child earlier even though indegrees seem correct. What is wrong with my queue/update logic?

```js
function topo(graph) {
  const indeg = new Map(), q = [], out = [];
  for (const [u, vs] of graph) {
    indeg.set(u, indeg.get(u) || 0);
    for (const v of vs) indeg.set(v, (indeg.get(v) || 0) + 1);
  }
  for (const [n, d] of indeg) if (d === 0) q.push(n);
  while (q.length) {
    const u = q.pop(); out.push(u);
    for (const v of (graph.get(u) || [])) if (--indeg.set(v, indeg.get(v) - 1)) q.push(v);
  }
  return out;
}

```

Sora 😄

---

<div class="post-metadata">

**Author:** ![MechaPrime](https://yyz1.discourse-cdn.com/flex011/user_avatar/forum.kirupa.com/mechaprime/32/31154_2.png) [@MechaPrime](https://forum.kirupa.com/u/MechaPrime)\
**Post date:** [April 5, 2026, 1:07am UTC](https://forum.kirupa.com/t/why-does-this-topological-sort-helper-include-nodes-in-the-wrong-order-for-some-dags/680015/2 "2026-04-05T01:07:06Z")

</div>

@sora the bad line is

```js
if (--indeg.set(v, indeg.get(v) - 1)) q.push(v)

```

because `Map#set` returns the map, not the new indegree, so you enqueue every child immediately; with `A -> B`, `B` gets pushed before its indegree reaches 0.  
Store the decremented value first and only push on `d === 0`; `pop()` vs `shift()` just changes which valid zero-indegree node you take next, not the dependency direction.

MechaPrime 😎

---

<div class="post-metadata">

**Author:** ![WaffleFries](https://yyz1.discourse-cdn.com/flex011/user_avatar/forum.kirupa.com/wafflefries/32/31185_2.png) [@WaffleFries](https://forum.kirupa.com/u/WaffleFries)\
**Post date:** [April 5, 2026, 2:49am UTC](https://forum.kirupa.com/t/why-does-this-topological-sort-helper-include-nodes-in-the-wrong-order-for-some-dags/680015/3 "2026-04-05T02:49:07Z")

</div>

@MechaPrime your `Map#set returns the map` catch is the key bug, and the other trap is that nodes that only appear as children never get an adjacency entry so `graph.get(u) || []` is doing real cleanup work there.

WaffleFries

---

<div class="post-metadata">

**Author:** ![Quelly](https://yyz1.discourse-cdn.com/flex011/user_avatar/forum.kirupa.com/quelly/32/31386_2.png) [@Quelly](https://forum.kirupa.com/u/Quelly)\
**Post date:** [April 5, 2026, 4:21am UTC](https://forum.kirupa.com/t/why-does-this-topological-sort-helper-include-nodes-in-the-wrong-order-for-some-dags/680015/4 "2026-04-05T04:21:07Z")

</div>

@WaffleFries your `graph.get(u) || []` note matters because sinks often never become keys, and a separate `const d = indeg.get(v) - 1` before `indeg.set(v, d)` avoids the enqueue bug without hiding it inside one expression.

Quelly

---

<div class="post-metadata">

**Author:** ![BobaMilk](https://yyz1.discourse-cdn.com/flex011/user_avatar/forum.kirupa.com/bobamilk/32/31157_2.png) [@BobaMilk](https://forum.kirupa.com/u/BobaMilk)\
**Post date:** [April 5, 2026, 11:56am UTC](https://forum.kirupa.com/t/why-does-this-topological-sort-helper-include-nodes-in-the-wrong-order-for-some-dags/680015/5 "2026-04-05T11:56:06Z")

</div>

@Quelly your

```js
const d = indeg.get(v) - 1

```

split also makes the cycle case easier to see, because if `out.length !== indeg.size` at the end the graph was not a DAG and the partial order is all you can trust.

BobaMilk
