pentaho/pentaho-kettle · error · KettleFileException

The database cache contains an empty row. We can't save…

Error message

The database cache contains an empty row. We can't save this!

What it means

DBCache.saveCache() iterates cached entries and writes each RowMetaInterface to disk. If an entry's row metadata is null (entry exists in the map but has no row), it throws KettleFileException 'The database cache contains an empty row. We can't save this!' because a null row cannot be serialized. This guards cache-file integrity.

Solutions

  1. Remove null-valued entries before saving (filter the cache map for null RowMetaInterface)
  2. Synchronize access to the DBCache so entries are only added together with their rows
  3. If triggered by a corrupt loaded cache, delete the cache file and restart so it rebuilds clean

Example fix

// before
saveCache(); // throws if any entry has null rowMeta
// after
cache.getMap().values().removeIf(Objects::isNull); // or guard inserts
saveCache();
Defensive patterns

Strategy: validation

Validate before calling

// Before saving, prune entries with null rows
map.values().removeIf(Objects::isNull);

Type guard

boolean isCacheEntrySavable(DBCacheEntry e, RowMetaInterface row) { return e != null && row != null; }

Try / catch

try { cache.savesCacheToDisk(); } catch (KettleFileException e) { if (e.getMessage().contains("empty row")) { /* clear cache and retry */ } else { throw e; } }

Prevention

When it happens

Trigger: Calling saveCache() (via savesCacheToDisk) while the in-memory cache contains a DBCacheEntry mapped to a null RowMetaInterface — typically from a race where an entry was inserted without its row, or code that cached a lookup before metadata was available.

Common situations: Concurrent access to the DB cache from multiple threads/steps where entries are added before rows; custom plugin code calling DBCache Fahne APIs incorrectly; a bug after deserializing a partially corrupt cache.

Related errors


AI-assisted analysis of pentaho/pentaho-kettle@f3058517a1 (2026-09-13). Data as JSON: /api/errors/9abb712bc995088b. Report an issue: GitHub.

Appendix: source

Thrown at core/src/main/java/org/pentaho/di/core/DBCache.java:192

      String filename = fileNameSupplier.get();
      File file = new File( filename );
      if ( !file.exists() || file.canWrite() ) {

        try ( DataOutputStream dos =
                new DataOutputStream( new BufferedOutputStream( new FileOutputStream( file ), 10000 ) ) ) {

          int counter = 0;

          for ( DBCacheEntry entry : cache.keySet() ) {
            entry.write( dos );

            // Save the corresponding row as well.
            RowMetaInterface rowMeta = get( entry );
            if ( rowMeta != null ) {
              rowMeta.writeMeta( dos );
              counter++;
            } else {
              throw new KettleFileException( "The database cache contains an empty row. We can't save this!" );
            }
          }
          log.logDetailed( "We wrote " + counter + " cached rows to the database cache!" );
        }
      } else {
        throw new KettleFileException( "We can't write to the cache file: " + filename );
      }
    } catch ( Exception e ) {
      throw new KettleFileException( "Couldn't write to the database cache", e );
    }
  }

  /**
   * Create the database cache instance by loading it from disk
   *
   * @return the database cache instance.
   */
  @SuppressWarnings( "squid:S00112" )

View on GitHub (pinned to f3058517a1)