components-contrib icon indicating copy to clipboard operation
components-contrib copied to clipboard

Local Storage Binding: List Operation Give Full Paths, Get Operation Expects Relative Paths

Open CraigCallender opened this issue 2 months ago • 3 comments

In what area(s)?

/area runtime

What version of Dapr?

  • Dapr Version: 1.15.6
  • OS: Linux
  • Component: bindings.localstorage
  • Component Version: v1

Expected Behavior

When using a curl commands to query a local storage binding, I would expect I could use the output of the list operation with the get operation.

Actual Behavior

When doing the above, the output of the list operation includes the full path to the file(s) on the local filesystem, but the get operation expects a relative path relative to the rootPath property in the component's YAML file.

Steps to Reproduce the Problem

Dapr Local Storage Binding Path Inconsistency - Reproduction Steps

Prerequisites

  • Dapr CLI installed
  • Docker installed (for Dapr runtime)

Step 1: Setup Dapr Component

Create a localstorage.yaml file:

apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
  name: localstorage
spec:
  type: bindings.localstorage
  version: v1
  metadata:
  - name: rootPath
    value: "/tmp/dapr-storage"

Step 2: Create Storage Directory

mkdir -p /tmp/dapr-storage/documents

Step 3: Start Dapr Runtime

# Start Dapr with the component
dapr run --app-id test-app --dapr-http-port 3500 --components-path . --app-port 8080 -- sleep 300

Note: The sleep 300 keeps the runtime alive for 5 minutes to run tests.

Step 4: Create Test Files via Dapr Binding

Create first test file:

curl -X POST "http://localhost:3500/v1.0/bindings/localstorage" \
  -H "Content-Type: application/json" \
  -d '{
    "operation": "create",
    "metadata": {
      "fileName": "documents/test1.json"
    },
    "data": "{\"id\": \"1\", \"content\": \"Test document 1\"}"
  }'

Create second test file:

curl -X POST "http://localhost:3500/v1.0/bindings/localstorage" \
  -H "Content-Type: application/json" \
  -d '{
    "operation": "create",
    "metadata": {
      "fileName": "documents/test2.json"
    },
    "data": "{\"id\": \"2\", \"content\": \"Test document 2\"}"
  }'

Create file in root directory:

curl -X POST "http://localhost:3500/v1.0/bindings/localstorage" \
  -H "Content-Type: application/json" \
  -d '{
    "operation": "create",
    "metadata": {
      "fileName": "root-file.txt"
    },
    "data": "This is a root level file"
  }'

Step 5: Verify Files Were Created

# Check filesystem directly
ls -la /tmp/dapr-storage/
ls -la /tmp/dapr-storage/documents/

Expected output:

/tmp/dapr-storage/
├── documents/
│   ├── test1.json
│   └── test2.json
└── root-file.txt

Step 6: List Files via Dapr (Shows the Bug)

List all files:

curl -X POST "http://localhost:3500/v1.0/bindings/localstorage" \
  -H "Content-Type: application/json" \
  -d '{
    "operation": "list",
    "metadata": {
      "fileName": "",
      "prefix": ""
    }
  }'

Expected Result: Relative paths like ["documents/test1.json", "documents/test2.json", "root-file.txt"]

Actual Result: Absolute paths like ["/tmp/dapr-storage/documents/test1.json", "/tmp/dapr-storage/documents/test2.json", "/tmp/dapr-storage/root-file.txt"]

List files with prefix:

curl -X POST "http://localhost:3500/v1.0/bindings/localstorage" \
  -H "Content-Type: application/json" \
  -d '{
    "operation": "list",
    "metadata": {
      "fileName": "documents/",
      "prefix": "documents/"
    }
  }'

Expected Result: ["documents/test1.json", "documents/test2.json"]

Actual Result: ["/tmp/dapr-storage/documents/test1.json", "/tmp/dapr-storage/documents/test2.json"]

Step 7: Demonstrate Get Operation Inconsistency

Try to get file using absolute path (from list result) - FAILS:

curl -X POST "http://localhost:3500/v1.0/bindings/localstorage" \
  -H "Content-Type: application/json" \
  -d '{
    "operation": "get",
    "metadata": {
      "fileName": "/tmp/dapr-storage/documents/test1.json"
    }
  }'

Result: Error or no data returned

Get file using relative path - WORKS:

curl -X POST "http://localhost:3500/v1.0/bindings/localstorage" \
  -H "Content-Type: application/json" \
  -d '{
    "operation": "get",
    "metadata": {
      "fileName": "documents/test1.json"
    }
  }'

Result: Successfully returns {"id": "1", "content": "Test document 1"}

Get root file using relative path - WORKS:

curl -X POST "http://localhost:3500/v1.0/bindings/localstorage" \
  -H "Content-Type: application/json" \
  -d '{
    "operation": "get",
    "metadata": {
      "fileName": "root-file.txt"
    }
  }'

Result: Successfully returns This is a root level file

The Problem

  1. List operation returns absolute paths that include the rootPath prefix
  2. Get operation expects relative paths from the rootPath
  3. Result: You cannot directly use the file paths returned by list in a get operation

This breaks the abstraction because:

  • Application code needs to know about the storage binding's rootPath configuration
  • Code needs to strip the absolute path prefix to make files accessible
  • Different storage bindings might behave differently, making code non-portable

Expected Behavior

The list operation should return relative paths consistent with what the get operation expects:

  • list should return: ["documents/test1.json", "documents/test2.json", "root-file.txt"]
  • get should accept: "documents/test1.json" (same format)

Cleanup

# Stop Dapr
# (Ctrl+C in the terminal where you ran dapr run)

# Clean up test files
rm -rf /tmp/dapr-storage

Release Note

RELEASE NOTE: FIX Aligned the output of the list operation with the expected input of the get operation for the localstorage binding.

CraigCallender avatar Oct 20 '25 07:10 CraigCallender

I opened this up in the wrong repo - but here's the original report: https://github.com/dapr/dapr/issues/8869

CraigCallender avatar Oct 20 '25 07:10 CraigCallender

This issue has been automatically marked as stale because it has not had activity in the last 30 days. It will be closed in the next 7 days unless it is tagged (pinned, good first issue, help wanted or triaged/resolved) or other activity occurs. Thank you for your contributions.

github-actions[bot] avatar Nov 19 '25 07:11 github-actions[bot]

commenting so it doesn't go stale.

CraigCallender avatar Nov 19 '25 08:11 CraigCallender