# Tool to enhance ERROR STOP messages

**URL:** <https://fortran-lang.discourse.group/t/tool-to-enhance-error-stop-messages/10749>\
**Category:** Uncategorized\
**Created:** [February 26, 2026, 8:54pm UTC](https://fortran-lang.discourse.group/t/tool-to-enhance-error-stop-messages/10749 "2026-02-26T20:54:23Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![Beliavsky](https://avatars.discourse-cdn.com/v4/letter/b/ba8739/32.png) [@Beliavsky](https://fortran-lang.discourse.group/u/Beliavsky)\
**Post date:** [February 26, 2026, 8:54pm UTC](https://fortran-lang.discourse.group/t/tool-to-enhance-error-stop-messages/10749/1 "2026-02-26T20:54:23Z")

</div>

`Error stop` unlike `stop` can be used in pure procedures and should be used to signal errors. [Pure-Fortran](https://github.com/Beliavsky/Pure-Fortran) has a script `xerror_loc.py` to enhance an `error stop` message by appending the line of the file, module, and procedure name and the values of the variables that triggered the error. For example, for the code

```fortran
module m
implicit none
contains
pure function dot(x, y) result(sum_xy)
real, intent(in) :: x(:), y(:)
real :: sum_xy
if (size(x) /= size(y)) error stop "size(x) /= size(y)"
sum_xy = sum(x*y)
end function dot
end module m

program main
use m
implicit none
print*,dot([2.0], [3.0, 4.0])
end program main

```

`python xerror_loc.py xerror_stop_dot.f90 --condition-values --run-both --out temp.f90`

gives

```auto
Applied 0 location tag rewrite(s) and 1 IF-block rewrite(s) across 1 file(s).
Build (original-fortran): gfortran xerror_stop_dot.f90 -o xerror_stop_dot.original-fortran.exe
<snip>
ERROR STOP size(x) /= size(y)

<snip>
Build (transformed-fortran): gfortran
<snip> 
Build (transformed-fortran): PASS
Run (transformed-fortran): temp.transformed-fortran.exe
Run (transformed-fortran): FAIL (exit 1)
ERROR STOP size(x) /= size(y) [temp.f90::module m::function dot::line 7]: size(x) = 1, size(y) = 2

```

In the error message for the transformed code, the line number of the error stop and the values of `size(x)` and `size(y)` are shown. You could print these before the error stop, but print is not allowed in pure functions. The new code around the error stop is

```fortran
   block
      character(len=1000) :: msg
      write(msg, "(a,a,g0,a,g0)") &
         & "size(x) /= size(y) [temp.f90::module m::function dot::line 7]", &
         & ": size(x) = ", size(x), ", &
         & size(y) = ", size(y)
      error stop trim(msg)
   end block

```

Using this tool you can get detailed information about why a program stopped without using a debugger or adding print statements (which may not be allowed).

---

<div class="post-metadata">

**Author:** ![Beliavsky](https://avatars.discourse-cdn.com/v4/letter/b/ba8739/32.png) [@Beliavsky](https://fortran-lang.discourse.group/u/Beliavsky)\
**Post date:** [February 27, 2026, 12:39am UTC](https://fortran-lang.discourse.group/t/tool-to-enhance-error-stop-messages/10749/2 "2026-02-27T00:39:39Z")

</div>

An `error stop` may be triggered by multiple conditions, as in

```fortran
module m
implicit none
contains
pure subroutine mmult(a, b, c)
real, intent(in) :: a(:,:)
real, intent(in) :: b(:,:)
real, intent(out) :: c(:,:)
if (size(a,2) /= size(b,1) .or. size(c,1) /= size(a,1) .or. &
   size(c,2) /= size(b,2)) error stop
c = matmul(a,b)
end subroutine mmult
end module m

program main
use m, only: mmult
implicit none
integer, parameter :: na1 = 3, na2 = 4, nb2 = 5
real :: a(na1, na2), b(na2, nb2), c(na1, nb2)
call random_number(a)
call random_number(b)
call mmult(a, b, c)
print*,c(1,1)
call mmult(a, b(:, 2:), c)
print*,c(1,1)
end program main

```

`python xerror_loc.py xmmult.f90 --specific --out temp.f90 --run`

gives an error message saying which condition caused termination, for example

```auto
ERROR STOP size(c,2) /= size(b,2) [temp.f90::module m::subroutine mmult::line 8]: size(c,2) = 5, size(b,2) = 4

```

for the code above. The `error stop` block in the transformed program is

```fortran
   block
      character(len=1000) :: msg
      character(len=*), parameter :: loc = &
         & "[temp.f90::module m::subroutine mmult::line 8]"
      if (size(a,2) /= size(b,1)) then
         write(msg, "(a,a,g0,a,g0)") "size(a,2) /= size(b,1) " // loc, &
            & ": size(a,2) = ", size(a,2), ", size(b,1) = ", size(b,1)
      else if (size(c,1) /= size(a,1)) then
         write(msg, "(a,a,g0,a,g0)") "size(c,1) /= size(a,1) " // loc, &
            & ": size(c,1) = ", size(c,1), ", size(a,1) = ", size(a,1)
      else
         write(msg, "(a,a,g0,a,g0)") "size(c,2) /= size(b,2) " // loc, &
            & ": size(c,2) = ", size(c,2), ", size(b,2) = ", size(b,2)
      end if
      error stop trim(msg)
   end block

```

Conditions are tested successively, and the first true condition is reported. If the original `error stop` test uses `any`, instead of repeated `.or.`, as in

```fortran
if (any([size(a,2) /= size(b,1), size(c,1) /= size(a,1), &
    size(c,2) /= size(b,2)])) error stop

```

the same error message is given.

---

<div class="post-metadata">

**Author:** ![jeff.irwin](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/jeff.irwin/32/3673_2.png) [@jeff.irwin](https://fortran-lang.discourse.group/u/jeff.irwin)\
**Post date:** [February 28, 2026, 9:08pm UTC](https://fortran-lang.discourse.group/t/tool-to-enhance-error-stop-messages/10749/3 "2026-02-28T21:08:24Z")

</div>

This is cool!

Another way to do part of this is to use the compiler-defined macros ` __FILE__ ` and ` __LINE__ `, which are supported by many compilers, at least `gfortran` and Intel. I use that for example in unit tests here: [fynth/test/test.F90 at 9def56a846a9dd305acc788d0d3f0c7d31a943da · JeffIrwin/fynth · GitHub](https://github.com/JeffIrwin/fynth/blob/9def56a846a9dd305acc788d0d3f0c7d31a943da/test/test.F90#L96)

```auto
#define TEST_EQ(val, expect, ntot) test_eq_str(val, expect, ntot, __FILE__ , __LINE__ )
integer function test_eq_str(val, expect, ntot, file_, line)
	character(len = *), intent(in) :: val, expect
	integer, intent(inout) :: ntot
	character(len = *), intent(in) :: file_
	integer, intent(in) :: line
	ntot = ntot + 1
	if (val == expect .and. len(val) == len(expect)) then
		test_eq_str = 0
	else
		test_eq_str = 1
		write(*,*) ERROR_STR//"str equality test failed at " &
			//file_//":"//to_str(line)
		write(*,*) " Received value: """, val, """"
		write(*,*) " Expected value: """, expect, """"
	end if
end function test_eq_str

```

---

<div class="post-metadata">

**Author:** ![sanjana\_chetry](https://avatars.discourse-cdn.com/v4/letter/s/85e7bf/32.png) [@sanjana\_chetry](https://fortran-lang.discourse.group/u/sanjana_chetry)\
**Post date:** [March 1, 2026, 10:31am UTC](https://fortran-lang.discourse.group/t/tool-to-enhance-error-stop-messages/10749/4 "2026-03-01T10:31:17Z")

</div>

Hi everyone,  
I’m exploring this idea as a potential GSoC project and trying to understand how ERROR STOP messages are currently produced across compilers.

I’m still getting familiar with the ecosystem, so I wanted to ask: in practice, where would richer context (like call stack or variable info) be most helpful?

Any pointers would be greatly appreciated.
