Both
If you want to write reliable and robust software, active "error prevention" in user input does not absolve you from checking validity afterwards and throwing a reasonable error message. You may limit the length and restrict input to numerals, etc., and think you've done enough, and then I'll paste from clipboard and oops! you forgot to process that.
(On that specific trick, the first instinct of a dumb designer is to block pasting, which should be a dismissible offence in itself. But even then, I've seen they often block Ctrl+V but not the more traditional Shift+Ins. The point is, don't ever think you are fully protected).
Sure, some controls can almost guarantee that the input will be valid. Say, you could make it a spin wheel or a numeric spin button, or a menu/combo list of fixed values. But all of them have usability issues: they usually require more user interactions (sometimes a lot more) than simply typing. Sometimes this prompts you (the designer) to limit the options to, say, rounds of 10 in the fixed list, instead of allowing every number from 0 to 100, even though there is no technical reason to do it. Such things may be more justifiable on a phone, but rarely are on a proper computer. In other words, by doing such things you are mostly trying to make your life easier (by thinking you can avoid processing wrong input), and may be even thinking you are helping the user, while doing everyone a disservice.
So, do help the user to avoid input errors, but not at the cost of a degraded experience and breaking conventions. And regardless of that, do provide error messages. (If you estimate that prevention is well designed and errors will be rare, the message may be curt and generic, but it has to be).
In your numeric input control, I would suggest the following (assuming it is mostly targeting a computer):
Do:
- Provide a helpful prompt. "Max: 100" is OK, but I would even suggest "0 to 100".
- Limit the entry to numeric characters only. (But don't assume it will be strictly enforced; e.g. due to possible copy-paste issue as mentioned above).
- But if you are doing it manually (most text controls have built-in "numeric only" mode), don't accidentally block Del, Backspace, arrows and any other control characters, including clipboard-related ones.
- Also, don't forget the minus if negative numbers are valid.
- If possible, highlight invalid input on the fly (e.g. different background or red frame), but never "fix" it (see below).
- On a computer, make sure the entire form is usable with keyboard only, without touching the mouse.
- (Optional) Provide increment/decrement of the current value (by a reasonable applicable amount) with the up/down keys, while applying the limits. But if the current input is not a number, don't assume it's 0 and destroy it, just don't do anything.
- Process leading zeros and leading/trailing blanks correctly; make sure 0010 is processed exactly as 10.
- Check for validity at the end in any case and provide a reasonable error message.
Don't
- Use overcomplicated and/or more restrictive controls such as fixed-list selection.
- Limit the text entry length to 3 and/or aggressively "fix" the user input on the fly. Always assume that the temporary value the user is typing may be invalid (especially if a default is provided and the user is expected to edit it, as opposed to typing anew). Nothing is more irritating than, while trying to edit "50" into "90" and temporarily making it a "950", a "smart" code that "helpfully" changes it to "100" (or worse, pops up a message).
- This especially applies to more complex forms where validity and/or limits may depend on other fields: don't force the user to comply to the fields he's about to change! For example, don't limit "Day" to 30 because "Month" is currently set to June: I'm going to select it later. This is a trivial example where it is more user-friendly to validate the whole form later and give an error message rather than aggressively prevent the user from entering "errors".
- Restrict copy-paste.
- Silently clip invalid values. Provide explicit errors instead.