Use case

My use case is to store environmental data downloaded from the Copernicus Marine Environment Monitoring Service (CMEMS) as netCDF files in GeoServer and make them available via Web Coverage Service using GetCoverage requests. I would like to be able to apply spatial, temporal and thematic subsetting. While spatial and temporal subsetting work smoothly (with subset parameter), I have trouble using thematic subsetting (with rangesubset parameter). Details are following below after explaining my setup first.


I use GeoServer 2.18.3 as part of a GeoNode setup, however the problems occur with GeoServer 2.18.2 and 2.20.3 outside of the GeoNode setup, too. Along my GeoServer installation I installed the two extensions netcdf and netcdf-out with the corresponding GeoServer version. In order to use scale_factor correctly I added -Dorg.geotools.coverage.io.netcdf.enhance.ScaleMissing=true to the JAVA_OPTS environment variable.

I have created a netCDF store with an example netCDF file (global-analysis-forecast-wav-001-027_20220101.nc, ~280 MB). Here is the output of ncdump -h:

netcdf global-analysis-forecast-wav-001-027_20220101 {
    time = 8 ;
    latitude = 2041 ;
    longitude = 4320 ;
    short VHM0(time, latitude, longitude) ;
        VHM0:_FillValue = -32767s ;
        VHM0:long_name = "Spectral significant wave height (Hm0)" ;
        VHM0:units = "m" ;
        VHM0:standard_name = "sea_surface_wave_significant_height" ;
        VHM0:cell_methods = "time:point area:mean" ;
        VHM0:type_of_analysis = "spectral analysis" ;
        VHM0:WMO_code = 100LL ;
        VHM0:_ChunkSizes = 1LL, 681LL, 1440LL ;
        VHM0:add_offset = 0. ;
        VHM0:scale_factor = 0.01 ;
    short VMDR(time, latitude, longitude) ;
        VMDR:_FillValue = -32767s ;
        VMDR:long_name = "Mean wave direction from (Mdir)" ;
        VMDR:units = "degree" ;
        VMDR:standard_name = "sea_surface_wave_from_direction" ;
        VMDR:cell_methods = "time:point area:mean" ;
        VMDR:type_of_analysis = "spectral analysis" ;
        VMDR:WMO_code = 200LL ;
        VMDR:_ChunkSizes = 1LL, 681LL, 1440LL ;
        VMDR:add_offset = 180. ;
        VMDR:scale_factor = 0.01 ;
    double longitude(longitude) ;
        longitude:_FillValue = NaN ;
        longitude:standard_name = "longitude" ;
        longitude:long_name = "longitude coordinate" ;
        longitude:units = "degrees_east" ;
        longitude:axis = "X" ;
        longitude:step = 0.08332825 ;
        longitude:_ChunkSizes = 4320LL ;
    double latitude(latitude) ;
        latitude:_FillValue = NaN ;
        latitude:standard_name = "latitude" ;
        latitude:long_name = "latitude coordinate" ;
        latitude:units = "degrees_north" ;
        latitude:axis = "Y" ;
        latitude:step = 0.08333588 ;
        latitude:_ChunkSizes = 2041LL ;
    double time(time) ;
        time:_FillValue = NaN ;
        time:standard_name = "time" ;
        time:long_name = "time" ;
        time:axis = "T" ;
        time:step = 3LL ;
        time:_ChunkSizes = 1LL ;
        time:units = "hours since 1950-01-01" ;
        time:calendar = "standard" ;

// global attributes:
        :Conventions = "CF-1.6" ;
        :time_coverage_start = "20220311-03:00:00" ;
        :time_coverage_end = "20220312-00:00:00" ;
        :date_created = "20220302-07:35:00" ;
        :product_type = "forecast" ;
        :product = "GLOBAL_ANALYSIS_FORECAST_WAV_001_027" ;
        :product_ref_date = "20220302-00:00:00" ;
        :product_range = "D+9" ;
        :product_user_manual = "http://marine.copernicus.eu/documents/PUM/CMEMS-GLO-PUM-001-027.pdf" ;
        :quality_information_document = " http://marine.copernicus.eu/documents/QUID/CMEMS-GLO-QUID-001-027." ;
        :dataset = "global-analysis-forecast-wav-001-027" ;
        :title = "Mean fields from global wave model MFWAM of Meteo-France with ECMWF forcing" ;
        :institution = "METEO-FRANCE" ;
        :references = "http://marine.copernicus.eu" ;
        :credit = "E.U. Copernicus Marine Service Information (CMEMS)" ;
        :licence = "http://marine.copernicus.eu/services-portfolio/service-commitments-and" ;
        :contact = "[email protected]" ;
        :producer = "CMEMS - Global Monitoring and Forecasting Centre" ;
        :area = "GLO" ;
        :geospatial_lon_min = -180. ;
        :geospatial_lon_max = 179.9167 ;
        :geospatial_lon_step = 0.08332825 ;
        :geospatial_lon_units = "degree" ;
        :geospatial_lat_min = -80. ;
        :geospatial_lat_max = 90. ;
        :geospatial_lat_step = 0.08333588 ;
        :geospatial_lat_units = "degree" ;

On top of this netCDF store I created a Coverage View including the two variables (in this order: VHM0, VMDR) as bands. Because I would like to use 10 or more variables in the end, I don’t want to use separate layers for each variable. In order to serve a long (~several months/years) time series of data I would like to use an ImageMosaic instead of a netCDF store later, but as the problems are identical I stick to the simpler case of a netCDF store in this post.


If I use the Coverage View to make the following GetCoverage request


I get a java.lang.NullPointerException:

geoserver_n52_geonode  | 30 Mar 13:53:39 INFO [org.vfny.geoserver.servlets] - OutputStream was successfully aborted.
geoserver_n52_geonode  | 30 Mar 13:53:39 ERROR [org.geoserver.ows] -
geoserver_n52_geonode  | java.lang.NullPointerException
geoserver_n52_geonode  |     at com.sun.media.jai.iterator.RandomIterFallback.makeCurrent(RandomIterFallback.java:110)
geoserver_n52_geonode  |     at com.sun.media.jai.iterator.RandomIterFallback.getSampleDouble(RandomIterFallback.java:133)
geoserver_n52_geonode  |     at org.geoserver.wcs.responses.AbstractNetCDFEncoder.setPixel(AbstractNetCDFEncoder.java:642)
geoserver_n52_geonode  |     at org.geoserver.wcs.responses.DefaultNetCDFEncoder.writeDataValues(DefaultNetCDFEncoder.java:423)
geoserver_n52_geonode  |     at org.geoserver.wcs.responses.AbstractNetCDFEncoder.write(AbstractNetCDFEncoder.java:482)

The full log with logging profile GEOTOOLS_DEVELOPER_LOGGING.properties applied can be found here: https://gist.github.com/MartinPontius/bd4ac2c6db4ac80f863c5bc298ba37ec

Interestingly with only the first band (VHM0) the server returns data correctly (apart from some minor naming/metadata issues). Making a request with both bands - i.e. using &rangesubset=VMDR,VHM0 - returns a netCDF file but only including one variable (always the first variable in the rangesubset list). I would expect to get a netCDF file containing both variables.

If I work with a different netCDF file (https://github.com/GeoNode/geoserver-restconfig/blob/master/test/data/polyphemus_20120401.nc) that is shown in some of the online examples (see https://geoserver.geo-solutions.it/multidim/multidim/netcdf/netcdf_config.html or https://geoserver.geo-solutions.it/multidim/multidim/imagemosaic/mosaic_indexer.html, actual file name is slightly different but should be very similar), the server returns data for separate bands correctly (same minor naming/metadata issues) - i.e. &rangesubset=N02 or &rangesubset=O3. However, if both bands are chosen - i.e. &rangesubset=N02,O3 - it only returns the first band again like with the other file.

Additional observations:

  • Using separate layers for each variable instead of a single Coverage View works
  • In the Layer preview with OpenLayers, GetFeatureInfo shows the correct values for both bands
  • Increasing the memory that GeoServer and JAI are allowed to use and removing WCS resource consumption limits didn’t help
  • Changing netCDF version from 4 to 3 didn’t help

Is there a known limitation in using rangesubset parameter with netCDF Coverage Views? Or do you have any idea what might be wrong with my installation and/or configuration?


Note: This applies only to the file/store global-analysis-forecast-wav-001-027_20220101.nc

The request above does work for the first band in the Coverage View (VHM0) as long as I use spatial subsetting. If I do not use it, I get a java.lang.NullPointerException again. Without spatial subsetting (with VMDR or VHM0) the error log (compare full log) is slightly different:

Mär 31, 2022 5:58:40 PM org.geoserver.GeoserverInitStartupListener$1 errorOccurred
INFORMATION: Problem occurs when computing a tile by the owner.
java.lang.RuntimeException: DataBuffer must have getOffsets().length equal to 1 or numBands.
    at javax.media.jai.RasterAccessor.<init>(RasterAccessor.java:505)
    at it.geosolutions.jaiext.mosaic.RasterAccessorExt.<init>(RasterAccessorExt.java:68)
    at it.geosolutions.jaiext.mosaic.MosaicOpImage.computeRect(MosaicOpImage.java:895)
    at it.geosolutions.jaiext.mosaic.MosaicOpImage.computeTile(MosaicOpImage.java:857)
    at com.sun.media.jai.util.SunTileScheduler.scheduleTile(SunTileScheduler.java:904)
    at javax.media.jai.OpImage.getTile(OpImage.java:1129)
    at javax.media.jai.RenderedOp.getTile(RenderedOp.java:2257)
    at com.sun.media.jai.iterator.RandomIterFallback.makeCurrent(RandomIterFallback.java:108)
    at com.sun.media.jai.iterator.RandomIterFallback.getSampleDouble(RandomIterFallback.java:133)
    at org.geoserver.wcs.responses.AbstractNetCDFEncoder.setPixel(AbstractNetCDFEncoder.java:644)
    at org.geoserver.wcs.responses.DefaultNetCDFEncoder.writeDataValues(DefaultNetCDFEncoder.java:431)
    at org.geoserver.wcs.responses.AbstractNetCDFEncoder.write(AbstractNetCDFEncoder.java:483)
    at org.geoserver.wcs.responses.NetCDFCoverageResponseDelegate.encode(NetCDFCoverageResponseDelegate.java:93)
    at org.geoserver.wcs2_0.response.WCS20GetCoverageResponse.write(WCS20GetCoverageResponse.java:103)

1 Answer 1


Not a known limitation. Your question seems material for a useful bug report:

  • Yes, the issue also occurs in versions 2.20.3 and the nightly/snapshot version 2.20.x (downloaded today). I opened a bug report as you suggested: osgeo-org.atlassian.net/browse/GEOS-10439. Let me know if any further information is needed/helpful.
    – martin
    Mar 31, 2022 at 15:51

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.