Known Issue: OGC GeoPackage Writer with Dynamic Schema Definition resolves aspatial table as geopackage_geometry, resulting in a malformed table

Dave Choi
Dave Choi
  • Updated
Known Issue ID FMEENGINE-99093
Feature OGC GeoPackage Writer and FeatureWriter
Product

FME Form

FME Flow

Versions Affected

2026.3.x

2026.2.x

2026.1.x

2025.x

2024.x

2023.x

Status

Resolved 

2026.4.x

Issue

When an OGC GeoPackage writer feature type uses Dynamic Schema Definition and the incoming schema specifies no geometry (fme_no_geom), the writer resolves the geometry type to geopackage_geometry rather than geopackage_none. The destination table is created as a spatial features table rather than a non-spatial attributes table, which results in a malformed table.

 

Symptom

In the log file, you will encounter the following entry for the layer without geometry:

OGCGEOPACKAGE writer: Creating layer '<Name of Feature Type>' with geometry type 'geopackage_geometry'

ArcGIS Pro users cannot open the affected table. Adding it to a map fails with:

 

QGIS users can still open the table and view its data.

 

Resolution

The issue has been fixed in FME 2026.4+ (including the current beta version). 

For FME 2026.3.x and older versions, you can permanently fix the behavior by editing a mapping file in the FME installation directory. You may need elevated permissions to edit the file.

If the workspace only runs on FME Flow, editing the FME Flow installation is enough. The steps below cover both FME Form and FME Flow to ensure parity in OGC GeoPackage geometry handling.

 

FME Form

  1. Close all FME Workbench sessions running the target FME version.
  2. Navigate to the FME Form installation directory, then to the metafile folder. The default is C:\Program Files\FME\metafile.

     

  3. Open ogcgeopackage.fmf.
  4. Go to line 112 and reorder the two fme_no_geom entries so GEOM_MAP geopackage_none fme_no_geom sits above GEOM_MAP geopackage_geometry fme_no_geom.

     

  5. Save the file.

 

FME Flow

  1. Navigate to the FME Flow installation directory, then to \Server\fme\metafile. The default is C:\Program Files\FMEFlow\Server\fme\metafile.

  2. Make the same edit to ogcgeopackage.fmf as described for FME Form, then save the file.
  3. Restart FME Flow.

Once the edit is in place, Dynamic Schema Definition resolves fme_no_geom to geopackage_none, and the writer creates an aspatial attributes table. Existing workspaces work as expected without any changes. Tables written before the fix still need to be rewritten.

 

Workarounds

The resolution may not be feasible in your situation; for example, if you cannot get elevated permissions to modify files in the FME installation or cannot restart FME Flow. In that case, use one of the workarounds below. 


Both workarounds require the FeatureWriter transformer rather than a standalone OGC GeoPackage writer. For demonstration, the workarounds below use a FeatureReader to read the data and schema. Any equivalent reader setup, such as a standalone Reader paired with a SchemaScanner, can be substituted for the FeatureReader.

The workspaces attached to this article are for demonstration and may need changes before you use them with your own data in production. Both workarounds include schema-first handling, which sorts each schema feature ahead of its data features. Without it, the writer can fail with OGCGEOPACKAGE writer: No definition found for input feature type, so keep this handling if you adapt the workspaces. If you are on FME 2026.3.x or older, we recommend applying the resolution above instead of the workspace workarounds, since it fixes the geometry behavior without workspace changes.

 

Workaround Option 1: Splitting the stream by geometry FME 2024.0+

This option splits the data stream before writing. Schema features and data features that have geometry are sorted so each schema feature arrives first, then goes to a normal dynamic feature type. No-geometry data, joined to its own schema feature, goes to a second dynamic feature type with Geometry set to geopackage_none. The following steps are added after the FeatureReader.

1. Add an AttributeExposer 

Connect the FeatureReader's <Schema> port to the AttributeExposer's Input port.

  • Attributes to Expose: fme_geometry{}

This makes the schema feature's geometry definition available to the Tester.

 

2. Add an AttributeCreator 

Connect the AttributeExposer's Output port to the AttributeCreator's Input port.

  • Output Attribute: SortKey
    • Value: 0
  • Output Attribute: fme_feature_type
    • Value: @Value(fme_feature_type_name)

Each schema feature now has a sort value and an fme_feature_type attribute, which the FeatureJoiner uses later.

 

3. Add a Tester

Connect the AttributeCreator's Output port to the Tester's Input port.

  • Test Clause:
    • Left Value: @Value(fme_geometry{0})
    • Operator: !=
    • Right Value: fme_no_geom

The Tester splits the schema features by geometry definition. Schema features with geometry exit through Passed, and schema features without geometry exit through Failed.

 

4. Add a FeatureTypeExtractor

Connect the FeatureReader's <Generic> port to the FeatureTypeExtractor's Input port.

  • Extracted Feature Type: fme_feature_type

This adds the feature type to every data feature. The FeatureJoiner uses this attribute in the next step.

 

5. Add a FeatureJoiner 

Connect the Tester's Failed port to the FeatureJoiner's Left port, and the FeatureTypeExtractor's Output port to the Right port.

  • Join On:
    • Left: fme_feature_type
    • Right: fme_feature_type

The FeatureJoiner attaches each no-geometry table's schema definition to every one of its data features, so schema and data reach the writer on the same feature. Data features with no matching no-geometry schema, which are the features with geometry, leave through the UnjoinedRight port.

 

6. Add an AttributeRemover

Connect the FeatureJoiner's Joined port to the AttributeRemover's Input port.

  • Attributes to Remove: fme_schema_handling

The joined data features inherit fme_schema_handling from their schema feature. Removing it makes the writer treat them as data features rather than schema-only features.

 

7. Add a Sorter

Connect the Tester's Passed port and the FeatureJoiner's UnjoinedRight port to the Sorter's Input port.

  • Group By: fme_feature_type
  • Sort By:
    • Attribute: SortKey
    • Alpha/Num: Numeric
    • Order: Descending

The Sorter sends each table's schema feature to the writer before its data features.

 

8. Add a FeatureWriter

Add two feature types to the FeatureWriter. Connect the Sorter's Sorted port to the first feature type, and the AttributeRemover's Output port to the second.

  • Format: OGC GeoPackage
  • Feature Type 1:
    • Feature Type Name: @Value(fme_feature_type)
    • Geometry: From Schema Definition
    • Dynamic Schema Definition: Enabled
      • Schema Sources: "Schema From Schema Feature"
  • Feature Type 2:
    • Feature Type Name: @Value(fme_feature_type)
    • Geometry: geopackage_none
    • Dynamic Schema Definition: Enabled
      • Schema Sources: "Schema From Schema Feature"

The first @Value(fme_feature_type) writes spatial tables as before. The second @Value(fme_feature_type) writes attribute tables because the fixed Geometry definition replaces the resolution step that triggers the bug. Your workspace should resemble the following screenshot:

In FME 2023, the writer does not honor Geometry set to geopackage_none in dynamic schema definition mode, so use the SQLExecutor workaround below.

 

Workaround Option 2: Correcting the table definition with an SQLExecutor FME 2023.0+

Option 2 writes the GeoPackage first, then repairs the affected tables in the same workspace. A GeoPackage is a SQLite database, so an SQLExecutor can rewrite the catalog entries that mark a table as spatial. This workaround is designed to read and write a single GeoPackage for demonstration purposes.

 

Before you start: Schema-first handling

The FME Form and FME Flow versions share the same start: the features are sorted so each table's schema feature reaches the FeatureWriter before its data features, the same way as Option 1. Add the following steps after the FeatureReader.

 

1. Add an AttributeCreator

Connect the FeatureReader's <Schema> port to the AttributeCreator's Input port.

  • Output Attribute: SortKey
    • Value: 0
  • Output Attribute: fme_feature_type
    • Value: @Value(fme_feature_type_name)

Each schema feature now has a sort value and the same fme_feature_type attribute the data features carry.

 

2. Add a FeatureTypeExtractor

Connect the FeatureReader's <Generic> port to the FeatureTypeExtractor's Input port.

  • Extracted Feature Type: fme_feature_type

This adds the feature type to every data feature so the Sorter can group it with its schema feature.

 

3. Add a Sorter. 

Connect the AttributeCreator's Output port and the FeatureTypeExtractor's Output port to the Sorter's Input port.

  • Group By: fme_feature_type
  • Sort By:
    • Attribute: SortKey
    • Alpha/Num: Numeric
    • Order: Descending

The Sorter sends each table's schema feature to the writer before its data features.

 

4. Add a FeatureWriter

Add one feature type and connect the Sorter's Sorted port to it.

  • Format: OGC GeoPackage
  • Feature Type:
    • Feature Type Name: @Value(fme_feature_type)
    • Geometry: From Schema Definition
    • Dynamic Schema Definition: Enabled
      • Schema Sources: "Schema From Schema Feature"
  • Output Ports: One per Feature Type

 

FME Form

After setting up the schema-first handling above, add the following steps after the FeatureWriter.

1. Add a FeatureMerger

Connect the FeatureWriter's @Value(fme_feature_type) output port to the FeatureMerger's Requestor port, and the FeatureWriter's Summary port to the Supplier port.

  • Join On:
    • Requestor: 1
    • Supplier: 1

The Summary feature carries _dataset, the path of the GeoPackage the FeatureWriter just wrote. Joining on a constant merges _dataset onto every written feature, so the SQLExecutor can target that file.

 

2. Add an AttributeExposer

Connect the FeatureMerger's Merged port to the AttributeExposer's Input port.

  • Attributes to Expose: fme_geometry{}

Exposing this attribute lets Workbench validate the Tester instead of flagging that the attribute does not exist.

 

3. Add a Tester

Connect the AttributeExposer's Output port to the Tester's Input port.

  • Test Clause 1:
    • Left Value: @Value(fme_geometry{0})
    • Operator: =
    • Right Value: fme_no_geom
  • Test Clause 2:
    • Logic: AND
    • Left Value: @Value(fme_schema_handling)
    • Operator: =
    • Right Value: schema_only

One schema feature passes for each no-geometry table, so the SQLExecutor runs once for each table to repair.

 

4. Add an SQLExecutor

Connect the Tester's Passed port to the SQLExecutor's Initiator port.

  • Format: OGC GeoPackage
  • Dataset: @Value(_dataset)
  • SQL Statement: Enter the statement below
    • When you click the ellipsis to open the SQL Statement editor, click Cancel in the Getting database table information dialog.

      FME_SQL_DELIMITER ;
      update gpkg_contents set data_type = 'attributes' where table_name = '@Value(fme_feature_type_name)';
      drop table if exists rtree_@Value(fme_feature_type_name)_geom_node;
      drop table if exists rtree_@Value(fme_feature_type_name)_geom_parent;
      drop table if exists rtree_@Value(fme_feature_type_name)_geom_rowid;
      drop trigger if exists rtree_@Value(fme_feature_type_name)_geom_insert;
      drop trigger if exists rtree_@Value(fme_feature_type_name)_geom_update1;
      drop trigger if exists rtree_@Value(fme_feature_type_name)_geom_update2;
      drop trigger if exists rtree_@Value(fme_feature_type_name)_geom_update3;
      drop trigger if exists rtree_@Value(fme_feature_type_name)_geom_update4;
      drop trigger if exists rtree_@Value(fme_feature_type_name)_geom_delete;
      alter table @Value(fme_feature_type_name) drop column geom;
      delete from gpkg_geometry_columns where table_name = '@Value(fme_feature_type_name)';
      delete from gpkg_extensions where table_name = '@Value(fme_feature_type_name)'

This converts the table from a spatial table to an attributes table by removing the empty geometry column and every catalog entry that refers to it.

Your workspace should look similar to the following screenshot:

FME Flow

The FME Flow version differs from the FME Form version because it runs as a Data Download service. The workspace reads a user-specified GeoPackage at runtime and writes the output GeoPackage to a temporary folder. The SQLExecutor then repairs the table, and a File Copy writer moves the repaired file to a download folder so the Data Download service can return it.

The workspace uses the same schema-first handling and builds on the FME Form version of Workaround Option 2. It adds two transformers before the FeatureReader and two after the SQLExecutor, and changes the FeatureReader and FeatureWriter settings. The workspace is attached to this article, so the steps below are brief.

1. Add an AttributeCreator

Add an AttributeCreator after the ParameterFetcher. 

  • Output Attribute: fme_basename
    • Value: @SubstringRegularExpression($(InputFile),[^\\/]+(?=\.gpkg$))

It extracts the file's base name from the input dataset path.

 

2. Update the FeatureReader

Set the FeatureReader to read the input dataset path.

  • Dataset: $(InputFile)

 

3. Update the GeoPackage FeatureWriter

  • Dataset: $(FME_SHAREDRESOURCE_TEMP)/$(FME_JOB_ID)/@Value(fme_basename).gpkg

4. Add an AttributeCreator

Connect the SQLExecutor's output to a new AttributeCreator.

  • Output Attribute: filecopy_source_dataset
    • Value: @Value(_dataset)

5. Add a File Copy FeatureWriter

Connect the AttributeCreator's Output port to a second FeatureWriter.

  • Format: File Copy
  • Dataset: $(FME_SHAREDRESOURCE_TEMP)/$(FME_JOB_ID)/download
  • Format Parameters:
    • File Operation: Move
    • Copy Subfolders: Yes
  • Subfolder Name: @Value(fme_basename)

Your workspace should look similar to the following screenshot:

When you publish the workspace, register it with the Data Download service and include only the File Copy writer in the download. The GeoPackage FeatureWriter writes the unrepaired file, so it should not be part of the download.

Was this article helpful?

We're sorry to hear that.

Please tell us why.