The writing wound up being on the wall, leading to the heartbreaking outcome that an IF that doesn't branch produces NULL, not VOID.
So to avoid getting an error on the nulls, you need an OPTIONAL or OPT or ? in there...
for 'n 100 [
print [
optional if n mod 3 = 0 ["Fizz"]
optional if n mod 5 = 0 ["Buzz"]
] else [
print [n]
]
]
for 'n 100 [
print [
opt if n mod 3 = 0 ["Fizz"]
opt if n mod 5 = 0 ["Buzz"]
] else [
print [n]
]
]
for 'n 100 [
print [
? if n mod 3 = 0 ["Fizz"]
? if n mod 5 = 0 ["Buzz"]
] else [
print [n]
]
]
Or, You Could Use An Empty ELSE Branch
for 'n 100 [
print [
if n mod 3 = 0 ["Fizz"] else []
if n mod 5 = 0 ["Buzz"] else []
] else [
print [n]
]
]
There's EITHER as well, but I don't want to put EITHER in an example like this.
Heart-Breaking, I Know 
None of these look as good as it did when it was just as the IF.
But voids are unstable by design--they can't be stored in variables, and they can't be boxed in an unstable pack that decays automatically. Plus ELSE needs to not run if something is VOID...that's reserved for the NULL state signaling BREAK. So you can't have an else-reactive IF that returns void.
And nulls cause an error state by design...we don't want PRINT to just be skipping over nulls like they're not there. You need an operator to stamp "vaporize this null". Needing the operator in a reduced example like this may feel unnecessary, but you quickly learn how important that guardrail is when working on actual code.
Making another named operation that's a "voiding IF" (such as WHEN) raises more questions than it solves, vs using an operator to erase nulls.
"A designer knows he has achieved perfection not when there is nothing left to add, but when there is nothing left to take away."
Have To Remember The Big Picture
We want rigorous foundations for building higher-level tools. Erroring on nulls that you don't explicitly suppress with OPT is part of that rigorous foundation.
Someone building real code that had this "FizzBuzz-like" problem often can build abstractions that remove the IF and its nulling concerns entirely:
How about a CASE+COLLECT hybrid, that is like CASE/ALL where it builds a block of results from all the branches that are taken?
print [unspaced collect-cases [
n mod 3 = 0 ["Fizz"]
n mod 5 = 0 ["Buzz"]
] else [n]]
This is the direction we need to stay laser-focused on...making it all work, so people can write these things effortlessly.
Note also the infix UNLESS proposal might be neat here:
print [n unless unspaced collect-cases [
n mod 3 = 0 ["Fizz"]
n mod 5 = 0 ["Buzz"]
]]
There's a whole discussion here, about the anatomy of a FizzBuzz...and I think it's becoming a really great diving off point to talk about the uniqueness of the language.