microsoft/semantic-kernel · error · ServiceResponseException

Upsert failed

Error message

Upsert failed

What it means

Raised in PostgresMemoryStore.upsert() when cur.fetchone() returns None after an INSERT ... RETURNING key. ServiceResponseException('Upsert failed') indicates the row was not returned despite the ON CONFLICT DO UPDATE ... RETURNING clause expecting a row. This is an unexpected DB response, not a normal not-found case.

Source

Thrown at python/semantic_kernel/connectors/memory_stores/postgres/postgres_memory_store.py:197

                        SET embedding = EXCLUDED.embedding,
                            metadata = EXCLUDED.metadata,
                            timestamp = EXCLUDED.timestamp
                        RETURNING key
                        """
                ).format(
                    scm=Identifier(self._schema),
                    tbl=Identifier(collection_name),
                ),
                (
                    record._id,
                    record.embedding.tolist(),
                    self.__serialize_metadata(record),
                    record._timestamp,
                ),
            )
            result = cur.fetchone()
            if result is None:
                raise ServiceResponseException("Upsert failed")
            return result[0]

    async def upsert_batch(self, collection_name: str, records: list[MemoryRecord]) -> list[str]:
        """Upserts a batch of records.

        Args:
            collection_name: The name of the collection to upsert the records into.
            records: The records to upsert.

        Returns:
            List[str]: The unique database keys of the records.
        """
        with self._connection_pool.connection() as conn, conn.cursor() as cur:
            if not await self.__does_collection_exist(cur, collection_name):
                raise ServiceResourceNotFoundError(f"Collection '{collection_name}' does not exist")
            cur.nextset()
            cur.executemany(
                SQL(

View on GitHub (pinned to c028a0c7dc)

Solutions

  1. Check DB logs for the actual statement error around the upsert timestamp.
  2. Verify the pgvector extension is installed and the embedding dimension matches the table's vector(N) column.
  3. Validate record.embedding length and that __serialize_metadata returns valid JSON before upsert.
  4. Recreate the connection pool if connections are stale; increase pool health checks.

Example fix

// before
await store.upsert("my_table", record)

// after
# validate before upsert
assert record.embedding.shape[0] == expected_dim
await store.upsert("my_table", record)
Defensive patterns

Strategy: try-catch

Validate before calling

assert record.embedding is not None and record.embedding.shape[0] == expected_dim
import json
json.loads(json.dumps(record.__dict__))  # ensure metadata is JSON-serializable
await store.upsert(collection_name, record)

Type guard

def is_valid_pg_record(record: MemoryRecord, dim: int) -> bool:
    return record.embedding is not None and record.embedding.shape[0] == dim

Try / catch

from semantic_kernel.exceptions import ServiceResponseException
try:
    await store.upsert(collection_name, record)
except ServiceResponseException as e:
    # 'Upsert failed' — check DB logs for the underlying statement error
    logger.error("postgres upsert returned no row: %s", e)
    raise

Prevention

When it happens

Trigger: The RETURNING clause produced no row — e.g., a DB-side rule rewrote the statement, a trigger suppressed the row, the connection was in a broken state, or a pgvector/serialization error left the statement non-returning. Most commonly a symptom of an underlying DB error surfacing as a missing return.

Common situations: Corrupt/timed-out connection from the pool; metadata serialization produced an invalid JSONB value; pgvector extension missing or dimension mismatch causing a silent statement failure; a BEFORE trigger returning NULL.

Related errors


AI-assisted analysis of microsoft/semantic-kernel@c028a0c7dc (2026-08-13). Data as JSON: /api/errors/c7c38a3d87a3ba3e. Report an issue: GitHub.