_Comment made by: hank_
The above leads to dodgy outcomes such as: The following expression leads to an Exception on 1st evaluation and to "w00t!" on subsequent ones.
(def delayed
  (let [a true]
    (delay
      (if a
        (throw (Exception.))
        "w00t!"))))
Try it like this:
(try
  (print "delayed 1:" )
  (println (force delayed))
  (catch Exception ex (println ex)))
(try
  (print "delayed 2:")
  (println (force delayed))
  (catch Exception ex (println ex)))
Results in:
delayed 1:#<Exception java.lang.Exception>
delayed 2:w00t!
This code shows that the problem is tied to the :once flag as suspected.
(def test-once
  (let [a true]
    (^{:once true} fn* foo []
        (println "a=" a)
        (throw (Exception.)))))
Invoking the fn twice will show 'a' turning from 'true' to 'nil', try it like this:
(try
  (print "test-once 1:")
  (test-once)
  (catch Exception ex (println ex)))
(try
  (print "test-once 2:")
  (test-once)
  (catch Exception ex (println ex)))
Results in:
test-once 1:a= true
#<Exception java.lang.Exception>
test-once 2:a= nil
#<Exception java.lang.Exception>
That doesn't happen when the ^{:once true} is removed. Now one could argue that above fn is invoked twice, which is exactly what one is not supposed to do when decorated with the :once flag, but I argue that an unsuccessful call doesn't count as invocation towards the :once flag. The delay and lazy-seq macros agree with me there as the resulting objects are not considered realized (as per realized? function) if the evaluation of the body throws an exception, and realization/evaluation of the body is therefore repeated on re-evaluation of the delay/lazy-seq.
Try this using (realized? delayed) after the first evaluation in the code above. In the implementation this can be seen e.g. [here for clojure.lang.Delay|
https://github.com/clojure/clojure/blob/d0c380d9809fd242bec688c7134e900f0bbedcac/src/jvm/clojure/lang/Delay.java#L33] (similarly for LazySeq), the body-fn is set to null (meaning realized) after the invocation returns *successfully* only.
The :once flag affects [this part of the compiler only|
https://github.com/clojure/clojure/blob/d0c380d9809fd242bec688c7134e900f0bbedcac/src/jvm/clojure/lang/Compiler.java#L4701]. Some field is set to nil there in the course of a function invocation, for the good reason of letting the garbage compiler collect objects, however this should to be done after the function successfully completes only. Can this be changed?