return an error rather than panic in withLock()