Mailing List Message #191
From: OCsite <>
Subject: Re: [WO-DEV] Cannot determine primary key for entity
Date: Sat, 12 Jun 2021 02:09:26 +0200
To: WebObjects & WOnder Development <>

On 11. 6. 2021, at 23:35, Samuel Pelletier <> wrote:
First thing to check is your data. Is the "uid" column has a non null or primary key constraint ?

Absolutely, it is the very PK; modelled as (the only) non-null integer key:

=== DBRecord.plist ===
      className = NSNumber;
      columnName = "C_UID";
      externalType = INTEGER;
      name = uid;
      valueType = i;
  attributesUsedForLocking = (
  primaryKeyAttributes = (
=== Database ===

Besides, it usually fetches all right, only occasionally fails — far as I can say, only when the background task happens to fetch at the same time. It is pretty difficult to catch the fail; I'm playing for hours and hours with the thing now, and so far I've succeeded to see ten-odd fails only (and I've tried to repeat the background threads unnecessarily, increase their number, etc., to increase the probability — so far in vain).

I've also meantime tried to
- lock the background thread ECs
- lock the background thread OSCs
- replace the return ERXEOControlUtilities.objectCountWithQualifier(this.editingContext, 'DBRecord', mymasterrow) code by
EOFetchSpecification fs=new EOFetchSpecification('DBRecord', mymasterrow, nil)
fs.rawRowKeyPaths=new NSArray('uid')
return this.editingContext.objectsWithFetchSpecification(fs).count()
Nothing helped. On the other hand, when I've
- switched off the background threads completely
- or, reduced ERXObjectStoreCoordinatorPool.maxCoordinators to 1 (which of course considerably slowed the app, for now the worker threads had to wait for the background tasks, using all the same DB channel)...

... the problem never occurred; either it really fixed it, or I was just not lucky enough to see it (see the low probability above).

Real weird.

If there is a constraint, can you indicate the database column type and model type used ?

Not sure what is a model type? Normal model, the .eomodeld folder containing all those plists; I've never seen any other. As for the rest, see please above.

Thanks and all the best,

Le 11 juin 2021 à 07:37, OCsite <> a écrit :

Hi there,

just bumped into another weird EOF case. A pretty plain fetch caused a “Cannot determine primary key for entity” exception. The row contains a number of columns whose values makes sense, some null, some non-null, with one exception — the primary key, modelled as an attribute uid, is indeed a null, thus the exception makes a perfect sense.

How can this happen?

IllegalArgumentException: Cannot determine primary key for entity DBRecord from row: {... uid = <$Null>; ... }
  at com.webobjects.eoaccess.EODatabaseChannel._fetchObject(
     ... skipped 2 stack elements
  at com.webobjects.eocontrol.EOObjectStoreCoordinator.objectsWithFetchSpecification(
  at com.webobjects.eocontrol.EOEditingContext.objectsWithFetchSpecification(
  at er.extensions.eof.ERXEC.objectsWithFetchSpecification(
     ... skipped 1 stack elements
  at com.webobjects.eocontrol.EOObjectStoreCoordinator.objectsForSourceGlobalID(
  at com.webobjects.eocontrol.EOEditingContext.objectsForSourceGlobalID(
  at er.extensions.eof.ERXEC.objectsForSourceGlobalID(
     ... skipped 1 stack elements
  at com.webobjects.eoaccess.EOAccessArrayFaultHandler.completeInitializationOfObject(
  at com.webobjects.eocontrol._EOCheapCopyMutableArray.willRead(
  at com.webobjects.eocontrol._EOCheapCopyMutableArray.count(

Just in case it happens to be important (I believe it is not), the problem happens at row

        ... =eolist.representedObject.records().isEmpty()?...:...

where records just returns storedValueForKey('records'), self-evidently a fault, which fires to fetch the rows.

Searching the Web, all I've found is this (linked from here), which does not really help :) Truth is, some background threads do run at the moment; they are comparatively plain though and I can't see why they should cause the problem for the R/R thread. All they do is to

1. get their own OSC from the pool, making sure they never get the same OSC normal sessions have
2. create a new ERXEC in this OSC
3. get a local instance of an object in the EC

=== this is the code of the background thread; a number of those runs:
        def store
        for (def pool=ERXObjectStoreCoordinatorPool._pool();;) {
            if (store!=_sessionosc) break // there's one OSC for all sessions, stored in _sessionosc
        return eo.localInstanceIn(ERXEC.newEditingContext(store)).numberOfMasterRowsWithoutOwner()

and the method simply fetches:

    int numberOfMasterRowsWithoutOwner {
        def mymasterrow=EOQualifier.qualifierWithQualifierFormat("importObject.dataBlock = %@ AND recordOwner = NULL",[this] as NSA)
        return ERXEOControlUtilities.objectCountWithQualifier(this.editingContext, 'DBRecord', mymasterrow)

Most time it works properly. Occasionally — rather rarely — the problem above happens. Can you see what am I doing wrong?

Thanks a lot,

Subscribe (FEED) Subscribe (DIGEST) Subscribe (INDEX) Unsubscribe Mail to Listmaster