Getting an error on hijacking write-stdout

old-write-stdout: copy :write-stdout

so-print: procedure [
    "Switch between using a print or a so-print operation for the bot"
    val [logic!]
][
    write %so-print.txt copy ""
    either val [
        print "so-print is now on"
        hijack 'write-stdout func [value][
            write/append %so-print.txt value
        ]
    ][
        hijack 'write-stdout :old-write-stdout
    ]
]

so-print on
print "hello"
so-print off

gives me this error

managed series was likely created during evaluator tick: 539490

What does this mean? And how do I fix it?

hijack needs to have the new function return the same type as the original function so we need to change the new function to be a proc

    so-print: procedure [
    "Switch between using a print or a so-print operation for the bot"
    val [logic!]
][
    write %so-print.txt copy ""
    either val [
        print "so-print is now on"
        hijack 'write-stdout proc [value][
            write/append %so-print.txt value
        ]
    ][
        hijack 'write-stdout :old-write-stdout
    ]
]

In debug builds, the message "managed series was likely created during evaluator tick..." is something you get when a "panic" condition is met. Panics are like Assertion Failures, but can carry more information to help diagnose the problem. If you are running a tool like Address Sanitizer or Valgrind, then you'll get significantly more information.

The problem you've run into here is that the REPL depends on PRINT deeply, and PRINT depends on WRITE-STDOUT. If you make a mistake in hijacking the behavior of PRINT it is a more serious kind of error, because it will fail at first and then fail during the report. Basically, it will create an unrecoverable error to break the version of PRINT that the console depends on.

There is some fledgling work at a "userspace echo" which does what you are trying to do:

>> echo on

>> 1 + 2
== 3

>> 3 + 4
== 7

>> echo off

>> read/lines %echo.txt
== [
    ""
    ">> 1 + 2"
    "== 3"
    ""
    ">> 3 + 4"
    "== 7"
    ""
    ">> echo off"
]

>> echo "cat"

>> 'meow 'meow
== meow

>> echo off

>> read/lines %echo-cat.txt
== [
    ""
    ">> 'meow 'meow"
    "== meow"
    ""
    ">> echo off"
]

>> echo [%custom * %-format.log]

>> echo on

>> "use blocks for templates"
== "use blocks for templates"

>> echo off

>> read/lines %custom-cat-format.log
== [
    ""
    ">> echo on"
    ""
    {>> "use blocks for templates"}
    {== "use blocks for templates"}
    ""
    ">> echo off"
]

>> echo reset

>> read/lines %custom-cat-format.log
== []

Truly writing a good echo requires tighter cooperation with the console code. The console is userspace (written in Rebol), so this is something interested users can work on improving:

Is it still a target to make STDOUT a port (presumably the default for SYSTEM/PORTS/OUTPUT)? I'd assume that you could just say system/ports/output: open %so-print.txt