`*file*` stays bound in a session after an eval with `:file`
Maintainers usually reply within 3 days
Nobody has claimed this yet.
Assessment
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Newbie friendliness
- 76/100
- Issue type
- Bug
- Clarity
- Clearly specified
- Activity status
- Active
- Domain
- backend, developer-experience
Research direction
Read src/clojure/nrepl/middleware/session.clj, especially the add-per-message-bindings and saved session bindings around lines 140 and 208–212. Reproduce the behavior with the provided eval and load-file sequence, then check how *file* behaves in the following eval. Done when evals without :file see "NO_SOURCE_PATH" and definitions no longer inherit the previous file metadata.
Written by the indexing model from the issue text.
Description
Found while working on neorepl: after neorepl load x.clj, neorepl where on a function defined later in the same session with neorepl eval pointed at x.clj.
Expected behavior
An eval without a :file sees *file* as "NO_SOURCE_PATH", whatever the session evaluated before it.
Actual behavior
The session keeps the *file* of its last eval with a :file, so everything defined there afterwards gets that file as its :file metadata, and compile errors are reported at it (Syntax error compiling at (/tmp/x.clj:1:1)). load-file does the same since 1.5, when it became an eval with :file.
add-per-message-bindings binds *file* only when the message has a :file (session.clj#L140-L141), and the bindings the session saves after each message drop only *msg* and Compiler/LOADER (session.clj#L208-L212). Binding *file* for every message, or dropping it there too, fixes it.
Steps to reproduce the problem
(require '[nrepl.core :as nrepl] '[nrepl.server :as server])
(with-open [srv (server/start-server :port 0)
conn (nrepl/connect :port (:port srv))]
(let [client (nrepl/client conn 60000)
values (fn [msg] (->> (nrepl/message client msg) (keep :value) vec))
check (fn [session sym]
(values {:op "eval" :session session
:code (format "(defn %s []) [*file* (select-keys (meta #'%s) [:file :line])]" sym sym)}))]
(let [session (-> (nrepl/message client {:op "clone"}) first :new-session)]
(prn :eval-before (check session "f1"))
(prn :eval-with-file (values {:op "eval" :session session :file "/tmp/x.clj" :code "*file*"}))
(prn :eval-after (check session "f2")))
;; load-file's :file is the file's contents, :file-path its path.
(let [session (-> (nrepl/message client {:op "clone"}) first :new-session)]
(prn :load-file (values {:op "load-file" :session session :file "*file*"
:file-path "/tmp/y.clj" :file-name "y.clj"}))
(prn :load-file-after (check session "f3")))))
(shutdown-agents)
:eval-before ["#'user/f1" "[\"NO_SOURCE_PATH\" {:file \"NO_SOURCE_PATH\", :line 1}]"]
:eval-with-file ["\"/tmp/x.clj\""]
:eval-after ["#'user/f2" "[\"/tmp/x.clj\" {:file \"/tmp/x.clj\", :line 1}]"]
:load-file ["\"/tmp/y.clj\""]
:load-file-after ["#'user/f3" "[\"/tmp/y.clj\" {:file \"/tmp/y.clj\", :line 1}]"]
Environment & Version information
Clojure version
1.12.5 (nREPL 1.8.0, master is the same)
Java version
21
Operating system
macOS 26.6
- Dominant language
- Clojure
- Stars
- 907
- Forks
- 111
- Avg merge
- 8d 10h
- Merged PRs (30d)
- 7
Getting set up
- No Dockerfile or Docker Compose file
- Has a pull request template
- Read the contributing guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from nrepl/nrepl
-
Evals take an extra 40ms each on Linux, since the server doesn't set TCP_NODELAYPossibly taken @bbatsov claimed this today. Open
Difficulty 2/5 1-3 hours Newbie friendliness 77/100
Maintainers usually reply within 3 days
-
(slurp *in*) leaves the session's stdin closed for goodMay be free again A pull request for this issue was closed without being merged. OpenBug
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
Maintainers usually reply within 3 days
-
Difficulty 4/5 1-2 days Newbie friendliness 55/100
Maintainers usually reply within 3 days
-
Difficulty 3/5 1-2 days Newbie friendliness 67/100
Maintainers usually reply within 3 days
-
Difficulty 4/5 3-5 days Newbie friendliness 45/100
Maintainers usually reply within 3 days
Similar issues
-
Difficulty 2/5 1-3 hours Newbie friendliness 90/100
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
Maintainers usually reply within 1 day
-
.Frontend .Team/UXWest Priority:P3 Querying/Filters Type:Bug
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
metabase/metabase#85298 · 1 comment ·
Maintainers usually reply within 1 day
-
pgwire
Difficulty 2/5 1-3 hours Newbie friendliness 77/100
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 66/100
software-mansion/starknet-jvm#641 ·