return nonzero on error