Zulip Chat Archive
Stream: metaprogramming / tactics
Topic: Error Propagation with tryCatch
Francisco Lima (Jul 15 2025 at 12:39):
I am making a automatic theorem solver, as such i need to loop over all available goals the best way I found yet has been to use a try catch with the getMainGoal but as shown in the following example it does not work, the catch pickups the error but the encompassing scope also receives the error for some reason, and only happens once as shown in the second case, so it only happens to the last goal
import Lean
open Lean Elab Meta Tactic
partial def loop (n := 0) : TacticM String :=
withMainContext do
try
let goal ← getMainGoal
admitGoal goal
let rest ← loop (n + 1)
return s!"sorry\n{rest}"
catch e =>
Lean.logInfo m!"Error: {e.toMessageData}"
return ""
syntax (name := endSorry) "sorry?" : tactic
elab_rules : tactic
| `(tactic| sorry?) => do
let raw ← loop
Lean.logInfo raw
return
theorem test : True := by
sorry?
theorem test2 : a → b → a ∧ b := by
intro a
intro b
apply And.intro
sorry?
Aaron Liu (Jul 15 2025 at 12:42):
Well if you logInfo the error obviously it's going to show up
Aaron Liu (Jul 15 2025 at 12:43):
what did you expect to happen
Francisco Lima (Jul 15 2025 at 12:44):
Aaron Liu said:
Well if you
logInfothe error obviously it's going to show up
the log is there to see it happens, but if the line is commented out the problem still happens (was happening before I started logging the error)
Aaron Liu (Jul 15 2025 at 12:45):
what's the problem you are experiencing
Francisco Lima (Jul 15 2025 at 12:46):
partial def loop (n := 0) : TacticM String :=
withMainContext do
try
let goal ← getMainGoal
admitGoal goal
let rest ← loop (n + 1)
return s!"sorry\n{rest}"
catch e =>
-- Lean.logInfo m!"Error: {e.toMessageData}"
return "error"
still gives the same 'error', that is, does not close with sorry the last goal
Aaron Liu (Jul 15 2025 at 12:47):
it seems to me that all the goals are closed though?
Aaron Liu (Jul 15 2025 at 12:47):
you can put done at the end of your by block and it doesn't complain
Francisco Lima (Jul 15 2025 at 12:48):
Francisco Lima (Jul 15 2025 at 12:48):
has the same error, does not close the last goal
Aaron Liu (Jul 15 2025 at 12:48):
interesting
Aaron Liu (Jul 15 2025 at 12:52):
if you return "" instead of return "error" I don't get a problem
Francisco Lima (Jul 15 2025 at 13:00):
In the actual code I do a return "" and the problem is still there
Francisco Lima (Jul 15 2025 at 13:05):
The content os the string, not doing some sort of throw should not matter for the final result
Francisco Lima (Jul 15 2025 at 15:35):
don't know if it matters but the problem doesn't seem to be connected with the try/catch since the following code has another error
import Lean
open Lean Elab Meta Tactic
partial def loop (n := 0) : TacticM String :=
withMainContext do
let goals ← getUnsolvedGoals
match goals with
| [] => return ""
| goal::_ =>
admitGoal goal
let rest ← loop (n + 1)
return s!"sorry\n{rest}"
syntax (name := endSorry) "sorry?" : tactic
elab_rules : tactic
| `(tactic| sorry?) => do
let raw ← loop
Lean.logInfo raw
return
theorem test : True := by
sorry?
done
theorem test2 : a → b → a ∧ b := by
intro a
intro b
apply And.intro
sorry?
done
Damiano Testa (Jul 15 2025 at 15:40):
Shouldn't loop call itself at n - 1, rather than n + 1? Also, if n = 0, you should exit "manually".
Francisco Lima (Jul 15 2025 at 16:00):
n in this case does not matter for the recursion or not, I am using it to keep track here of how deep it has gone, in the actual code it increases as it goes along to keep track of variable naming (crude solution but it works)
Francisco Lima (Jul 15 2025 at 16:02):
with a bit more of logging I discovered it throws the error before the getMainGoal call (or at least it supresses the log)
import Lean
open Lean Elab Meta Tactic
partial def loop (n := 0) : TacticM String :=
withMainContext do
try
Lean.logInfo s!"Pre {n}"
let goal ← getMainGoal
admitGoal goal
let rest ← loop (n + 1)
return s!"sorry {n}\n{rest}"
catch e =>
-- Lean.logInfo m!"Error: {e.toMessageData}"
return s!"error {n}"
syntax (name := endSorry) "sorry?" : tactic
elab_rules : tactic
| `(tactic| sorry?) => do
let raw ← loop
Lean.logInfo raw
return
theorem test {a : Prop} : a → a := by
intro a
sorry?
-- Expect:
-- sorry 0
-- error 1
done
theorem test2 : a → b → a ∧ b := by
intro a
intro b
apply And.intro
sorry?
-- Expect:
-- sorry 0
-- sorry 1
-- error 2
done
Last updated: Dec 20 2025 at 21:32 UTC