on errors, buff needs to be freed