豆豆友情提示:这是一个非官方 GitHub 代理镜像,主要用于网络测试或访问加速。请勿在此进行登录、注册或处理任何敏感信息。进行这些操作请务必访问官方网站 github.com。 Raw 内容也通过此代理提供。
Skip to content

Memory subcommands still hang on v3.5.75 — original fix in #1453 appears incomplete #1550

@coachhype

Description

@coachhype

Summary

ruflo memory store and ruflo memory search (and likely all other memory * subcommands) functionally complete in milliseconds but the Node process never exits. Reproducible on v3.5.75 (latest at the time of writing, 2026-04-07).

This appears to be a regression or incomplete fix of #1453 ("fix: ruflo memory subcommands hang after completion — process.exit() missing from CLI entry point"), which was marked closed on 2026-04-02 but the symptom is still present.

Related: PR #1441 ("fix(cli): process.exit at entry point to prevent ONNX event loop hang") is marked open and may be the actual fix that hasn't shipped yet.

Environment

  • Ruflo / claude-flow version: v3.5.75 (verified via ruflo --version)
  • Install method: npm install -g ruflo@latest (global, not npx-cached)
  • Node: v24.14.1
  • npm: v11.11.0
  • OS: macOS 14 (Darwin 25.4.0, arm64)

Reproducer

mkdir -p /tmp/ruflo-mem-repro && cd /tmp/ruflo-mem-repro
ruflo init --full
ruflo memory init

ruflo memory store -k "test-key" -v "test value"
# never returns; manually kill with Ctrl+C

ruflo memory search -q "test"
# same — never returns

What actually happens

The operation completes successfully in ~3-5 ms. Output is correct. The process just never calls process.exit() after the operation finishes.

Captured via background + sleep + kill pattern (the workaround):

ruflo memory search -q "test" > /tmp/mem.log 2>&1 & PID=$!
sleep 3
kill -9 $PID
cat /tmp/mem.log

Output of cat /tmp/mem.log after killing the hung process:

[INFO] Searching: "test" (semantic)

  Search time: 3ms

+----------------------+-------+-----------+----------------------------+
| Key                  | Score | Namespace | Preview                    |
+----------------------+-------+-----------+----------------------------+
| test-key             |  0.43 | default   | test value                 |
+----------------------+-------+-----------+----------------------------+

[INFO] Found 1 results

The actual semantic search runs in 3 ms and returns the right result. The hang is purely the Node process not exiting after the function returns.

Expected

ruflo memory store ... and ruflo memory search ... should print their output and exit cleanly with exit code 0, just like ruflo --version, ruflo doctor, and other working subcommands.

Workaround currently in use

ruflo memory <subcommand> ARGS > /tmp/mem.log 2>&1 & PID=$!
sleep 3
kill -9 $PID 2>/dev/null
cat /tmp/mem.log

Works reliably because the actual operation takes <10 ms; the sleep is only there to make sure stdout is flushed before the SIGKILL. Anything that uses ruflo memory * programmatically has to wrap every call in this pattern, which is painful in scripts and impossible in interactive npx use.

Suspected root cause

Same family as #1453, #1428, and #1395: something keeps the Node event loop alive after the user-facing operation completes — most likely the ONNX worker threads (the agentic-flow embedding subsystem the memory tools use for the 384-dim semantic vectors), or housekeeping timers that aren't unref()-ed.

#1269 added .unref() to housekeeping timers but the symptom returned. PR #1441 proposes adding an explicit process.exit(0) at the CLI entry point after the command's main returns — that would force-exit regardless of dangling event loop refs. Whatever shipped between #1453 closing and v3.5.75 either doesn't cover the memory store / memory search paths or was rolled back.

Why this matters

Memory store and search are foundational to the self-learning loop the README pitches at L613-620 (the "LEARN → COORD → EXECUTE → REMEMBER" cycle). With these commands hanging, the cycle is broken for anyone scripting against ruflo memory *. The workaround works for shell users but doesn't help the MCP path or any programmatic consumer.

Happy to help

If a maintainer wants me to:

  • Run the reproducer with extra debug flags
  • Test a specific commit / PR build
  • Capture an active-handles dump (process._getActiveHandles()) at the moment of hang

just say the word and I'll attach the output to this thread.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions