This is due to the bit confusing API. It has growen over time…
You read the pixel values directly by the readPixels(). This does not create the internal data holder of the band which is necessary when using setPixels().
You can now use instead of setPixels() the writePixels() method or you replace readPixels() by getPixels(). Before the first call to getPixels() you need to call loadRasterData().
There are two pairs of methods, get and set and write and read.
However writePixels actually writes into the disk right?
What if we just want to create a new band and then write the new product onto a different file?
In this case you can create a new product and add a new band. Dimensions should be kept the same.
Then call on the band ensureRasterData(). This will create an internal data buffer which holds the data.
Then you can use setPixels methods. Afterwards you can use ProductIO to write the product.
Probably you want to keep the geo-information.
Use ProductUtils.copyGeoCoding(oldProduct, newProduct)
Marco from EOMasters - Mastering Earth Observation