ReturnHeaders gives the same result. Somehow something is writing something back to the browser that confuses it. I narrowed down the part of set_form_variables that was causing this to the ns_getform call, and the part of ns_getform that makes it break is
set n [ns_set size $_ns_form]
for {set i 0} {$i < $n} {incr i} {
set key [ns_set key $_ns_form $i]
set value [ns_set value $_ns_form $i]
set value [ns_set value $_ns_form $i]
set newvalue [encoding convertfrom $encoding $value]
ns_set put $newform $key $newvalue
}
Any of the ns_set calls here (size, key, value) break the ReturnHeaders and redirect. Removing all of them makes the redirect work fine. (Of course, that renders ns_getform completely useless.)