gismanager quirks
Reference material. Each quirk lists the symptom, the root cause, and the file:line where the workaround lives. Whenever you change any code that talks to GDAL or to GeoServer, scan this list for relevance.
1. Layer.Feature(...) takes int64, not int
- Symptom:
cannot use index (type int) as type int64 in argument to Layer.Featurefromlukeroth/gdal. Build fails on Go 1.13+. - Root cause: Upstream's 2022 API sweep moved feature IDs from
inttoint64. The pre-revival code was written against the older signature and never bumped — issue #1. - Workaround: Cast
indextoint64at the call site. - Where:
layer.go:172inGetFeatures.
2. mholt/archiver is deprecated; use stdlib archive/zip
- Symptom:
(*archiver.Zip).Openrequires a pointer receiver in v3+; older code callingarchiver.Zip.Open(value receiver) fails to build. Upstream is also flagged DEPRECATED in the README. - Root cause:
mholt/archiverwas deprecated in 2024 in favor ofmholt/archives(which is itself pre-1.0 as of mid-2026). - Workaround: Drop the dep entirely. gismanager only used the Zip extraction; stdlib
archive/zipdoes it cleanly. Custom extractor lives ininternal/zipx/extract.gowith zip-slip rejection (filepath.Rel based, recognized by CodeQL'sgo/zipslipquery) and a 2 GiB per-entry size cap (gosec G110). - Where:
internal/zipx/extract.go; called fromutils.go:104(zippedShapeFile).
3. PostGIS feature-type creation requires the table to have non-geometry attributes
- Symptom:
POST /workspaces/{ws}/datastores/{ds}/featuretypesreturns400 "Trying to create new feature type inside the store, but no attributes were specified"if the target PostGIS table is empty or has only the geometry column. - Root cause: GeoServer's wire-format expects the schema to have at least one attribute besides the geometry column to publish a feature type.
- Workaround: gismanager uses OGR's
CopyLayerto materialize the PostGIS table from the source GIS file, which preserves the source schema (geometry + attributes). The integration suite verifies this by publishing a real GeoJSON with attribute fields. Don't introduce a "publish empty stub" code path without addressing the upstream constraint. - Where:
layer.go::LayerToPostgis(usesdatasource.CopyLayer); integration testpublish_integration_test.go::TestPublishGeoJSON_EndToEnd_Integration.
4. v2 GeoServer client has no Exists method — use Get + errors.Is(err, geoserver.ErrNotFound)
- Symptom: Pre-revival code called
catalog.WorkspaceExists(name)/DatastoreExists(...). The v2 client doesn't expose those. - Root cause: Deliberate v2 design —
Get+ sentinel matching is more flexible than a boolean (it preserves the underlying*geoserver.APIErrorfor 5xx vs 404 disambiguation). - Workaround: The publish flow in
layer.godoesc.Workspaces.Get(ctx, name)first; if it returnsErrNotFound, callsCreate; any other error short-circuits. Same pattern for datastore + feature type. - Where:
layer.go::ensureWorkspace,ensureDatastore, plus the inline featuretype check inPublishGeoserverLayer.
5. Don't apt-get install libgdal-dev on the OSGeo image
- Symptom: Runtime crash with
error while loading shared libraries: libgdal.so.34: cannot open shared object file: No such file or directory. - Root cause: The OSGeo image (
ghcr.io/osgeo/gdal:ubuntu-small-3.12.4) ships its own GDAL (3.12.4 →libgdal.so.38). Ubuntu 24's apt has GDAL 3.6 →libgdal.so.34. Installing the apt version on top shadows the bundled headers, so the binary links against the older soname which then doesn't exist at runtime. - Workaround: Don't apt-install anything GDAL-named. The OSGeo image already provides headers at
/usr/include/gdal_*.hand a pkg-config file at/usr/lib/x86_64-linux-gnu/pkgconfig/gdal.pc. - Where:
Dockerfileapt-install line (commented to flag the trap).
6. Go 1.25.x stdlib CVEs (GO-2026-4869 / 4865 / 4603 …)
- Symptom:
govulncheckflags 10+ stdlib vulnerabilities on Go 1.25.3. - Root cause: Upstream Go security cadence — patches land in 1.25.x point releases.
- Workaround: Pin
GO_VERSION=1.25.9inDockerfile. When Go 1.25.10+ ships, bump. - Where:
DockerfileARGGO_VERSION.
7. golangci-lint v2 needs golangci-lint-action v7
- Symptom: CI Lint job fails with
invalid version string 'v2.12.1', golangci-lint v2 is not supported by golangci-lint-action v6. - Root cause: Action v6 only supports v1.x; v7 is the v2-aware release.
- Workaround: Pin the action to
golangci/golangci-lint-action@v7in.github/workflows/ci.yml. - Where:
.github/workflows/ci.yml::Lint.
8. GOFLAGS=-buildvcs=false required when go-build runs in a container
- Symptom:
error obtaining VCS status: exit status 128fromgo buildin CI. - Root cause: The mounted
.gitdirectory is owned by a different uid than the runner-user; git refuses to operate on it for security reasons. - Workaround: Set
GOFLAGS=-buildvcs=falseat the workflowenv:level (the dev image has it baked in viaDockerfileENV; on Actions the setup-go step inherits its own env so we set it again). - Where:
.github/workflows/ci.yml::env,.github/workflows/integration.yml::env(if present).
When this catalog is most useful
- Implementing a new GIS-format ingest path — scan items 1, 2, 5 before writing the OGR open.
- Debugging an integration-test failure with
unmarshal/5xx/no attributes— items 3, 4 are the usual suspects. - Bumping GDAL or Go in
Dockerfile— items 5, 6 are the gotchas. - A CI gate flipping red after a workflow / dependency bump — items 7, 8 cover the recurring traps.
Source: hishamkaram/gismanager — distributed by TomeVault.