Skip to content

Panic in construct.rs:217 when recalling variable from previous HTTP request #5

@seanthechancellor-create

Description

Bug Description

When using the HTTP API (POST /v1/query), variables created with +variable in one request cannot be recalled in a subsequent request. The second request panics at construct.rs:217 with called Option::unwrap() on a None value, which poisons the internal Mutex and makes the server unresponsive to all further requests (every subsequent request returns PoisonError).

Environment

  • Positorium v0.1.4 (built from master, commit HEAD)
  • Platform: WSL2 Ubuntu, Linux 6.6.87
  • Rust: 1.92.0

Steps to Reproduce

# Start fresh
rm -f positorium.db && ./target/release/positorium &
sleep 4

# Request 1: create a role and a thing — WORKS
curl -s http://127.0.0.1:8080/v1/query \
  -H "Content-Type: application/json" \
  -d '{"script":"add role name; add posit [{(+alice, name)}, \"Alice\", '\''2024-01-01'\''];","stream":false}'
# Returns: {"status":"ok",...}

# Request 2: recall the same variable — PANICS
curl -s http://127.0.0.1:8080/v1/query \
  -H "Content-Type: application/json" \
  -d '{"script":"add posit [{(alice, name)}, \"Alice Updated\", '\''2025-01-01'\''];","stream":false}'
# Returns: "Join error" (HTTP 500)
# Server log: thread 'tokio-runtime-worker' panicked at src/construct.rs:217:40

Expected Behavior

Either:

  1. Variables from previous requests are accessible in subsequent requests (session-like behavior), OR
  2. A clear error message like "Unknown variable 'alice'" instead of a panic

Actual Behavior

  • construct.rs:217 panics with unwrap() on None
  • The panic poisons the Mutex, making the entire server permanently unresponsive
  • All subsequent requests (even valid ones) return PoisonError
  • The only recovery is to restart the process

Workaround

Combine all posits that share variables into a single request using comma-separated syntax:

# This works — both posits in one script, variable persists within execution
curl -s http://127.0.0.1:8080/v1/query \
  -H "Content-Type: application/json" \
  -d '{"script":"add role name; add posit [{(+alice, name)}, \"Alice\", '\''2024-01-01'\''], [{(alice, name)}, \"Alice Updated\", '\''2025-01-01'\''];","stream":false}'

Additional Context

The startup script path (traqula_file_to_run_on_startup) does not have this issue because it executes in a single Engine context. The bug is specific to the HTTP server path where each request creates a fresh Engine instance, so variables from previous requests are not in scope.

The Mutex poisoning is a secondary issue — even if the variable recall is expected to fail, the panic should be caught and returned as an error response rather than crashing the thread and poisoning shared state.

Suggested Fix

  1. In construct.rs:217, replace .unwrap() with .ok_or(DatabaseError::Execution {...}) to return an error instead of panicking
  2. In server.rs, wrap the engine execution in std::panic::catch_unwind() to prevent Mutex poisoning from unhandled panics

Thank you for building Positorium — it's a remarkable piece of work. We're using it as the bitemporal evidence layer in a compliance automation pipeline alongside TypeDB and Alloy 6.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions