In reply to le_NOIRE2000:
Typically one separates data associated with transaction from the protocol in the interface used to drive the transaction. All data in the transaction should be initialized by the generator. This makes it easier to maintain changes to your protocol as well as making your generators and drivers more re-usable in other parts of the same design, or other designs.
I assume your “valid” bit is part of the protocol. Dealing with errors in the protocol probably requires using a different driver task. In an Object-Oriented testbench, you would override the driver class with an Error_driver for a particular test.
These are general guidelines that fit most situations.