What's Actually Happening

OPA Rego policy file has syntax errors. Policy cannot be parsed or loaded by OPA.

The Error You'll See

```bash $ opa check policy.rego

policy.rego:5: rego_parse_error: unexpected identifier token: if ```

Missing package:

bash
policy.rego:1: rego_parse_error: package declaration required

Invalid rule syntax:

bash
policy.rego:10: rego_parse_error: rule head must be identifier or reference

Operator error:

bash
policy.rego:15: rego_parse_error: invalid comparison operator

Why This Happens

  1. 1.Missing package - No package declaration at file start
  2. 2.Invalid keywords - Wrong keyword usage (if, else, some)
  3. 3.Brace errors - Missing or mismatched braces
  4. 4.Operator errors - Invalid comparison or arithmetic operators
  5. 5.Comment syntax - Wrong comment format
  6. 6.Import issues - Missing or invalid imports

Step 1: Add Package Declaration

```rego # Every Rego file must start with package declaration:

# BAD: allow { input.role == "admin" }

# GOOD: package policy

allow if { input.role == "admin" }

# Package name format: package auth.policy # Nested package package myapp # Simple package

# Package must be first non-comment line: # File: auth.rego package auth

allow if { input.user == "admin" }

# Then evaluate: opa eval -d auth.rego 'data.auth.allow' ```

Step 2: Fix Rule Syntax

```rego # Rego v1 syntax (recommended):

# Rule with if: allow if { input.role == "admin" }

# Rule without body (constant): default allow := false

# Partial rule set: roles contains "admin" if { input.is_admin }

# Rule with value: message := "Access granted" if { allow }

# OLD syntax (deprecated but works): # allow { # input.role == "admin" # }

# Rule head must be identifier: # BAD: 123_allow if { ... } # Starts with number # GOOD: allow_123 if { ... }

# Rule with arguments: is_admin(user) if { user.role == "admin" } ```

Step 3: Fix Braces and Structure

```rego # Rego uses braces for rule bodies and sets:

# Rule body braces: allow if { input.role == "admin" # Condition input.active == true # Another condition } # All conditions must be true for rule to be true

# Set braces (values): roles := {"admin", "user", "guest"}

# Object braces (key-value pairs): config := { "host": "localhost", "port": 8080 }

# Comprehension braces: admin_users := { user | some user in input.users user.role == "admin" }

# Missing braces error: # BAD: allow if input.role == "admin" # Missing braces!

# GOOD: allow if { input.role == "admin" }

# Mismatched braces: # BAD: allow if { input.role == "admin" } } # Extra brace

# GOOD: allow if { input.role == "admin" } ```

Step 4: Fix Comparison Operators

```rego # Valid comparison operators:

# Equality: input.role == "admin" input.id != 100

# Comparison: input.age > 18 input.age >= 18 input.age < 65 input.age <= 65

# Invalid operators: # BAD: input.role = "admin" # Single = is assignment, not comparison input.role === "admin" # Not valid in Rego input.role <> "admin" # Not valid in Rego

# GOOD: input.role == "admin"

# Assignment operator: x := 5 y = input.value # Also valid for assignment

# Logical operators: allow if { input.role == "admin" input.active == true # AND (implicit) }

allow if { input.role == "admin" } else if { input.role == "user" # OR (else if) }

# Or operator: allow if { input.role == "admin" or input.role == "superuser" } ```

Step 5: Fix Iteration Syntax

```rego # Rego v1 iteration with some:

# Iterate array: some user in input.users user.role == "admin"

# Iterate with index: some i, user in input.users user.role == "admin" i < 10

# Iterate object: some key, value in input.config key == "host"

# OLD syntax (deprecated): # user := input.users[_] # user.role == "admin"

# Comprehension iteration: admin_users := { user.name | some user in input.users user.role == "admin" }

# Array comprehension: admin_names := [ user.name | some user in input.users user.role == "admin" ]

# Invalid iteration: # BAD: for user in input.users { # No for loop in Rego! user.role == "admin" }

# GOOD: some user in input.users user.role == "admin" ```

Step 6: Fix Comments

```rego # Comments in Rego:

# Line comment (starts with #): # This is a comment allow if { input.role == "admin" # Inline comment }

# Block comments (multiple #): # This is a # multi-line # comment

# Invalid comment: # BAD: // Not a comment! // syntax not valid /* Not valid */ # /* */ syntax not valid

# GOOD: # Use # for all comments

# Comment at end of line: allow if { input.role == "admin" # Check role }

# Document rules with comments: # Allow access if user is admin # and account is active allow if { input.role == "admin" input.active == true } ```

Step 7: Fix Import Statements

```rego # Import statements:

# Import built-in functions: import future.keywords.if import future.keywords.contains

# With imports, use new syntax: package policy

import future.keywords.if

allow if { input.role == "admin" }

# Import external data: import data.users

allow if { some user in users user.name == input.user user.role == "admin" }

# Invalid import: # BAD: import "future.keywords.if" # Not a string

# GOOD: import future.keywords.if

# Import from other package: import data.auth.users ```

Step 8: Fix Functions

```rego # Functions in Rego:

# Function definition: is_admin(user) if { user.role == "admin" }

# Function call: allow if { is_admin(input.user) }

# Function with return value: get_role(user) := user.role

# Use return value: role := get_role(input.user)

# Function with multiple args: has_permission(user, action) if { some perm in user.permissions perm == action }

# Invalid function: # BAD: function is_admin(user) { # No function keyword return user.role == "admin" }

# GOOD: is_admin(user) if { user.role == "admin" } ```

Step 9: Fix Else Statements

```rego # Else statements:

# Simple else: allow if { input.role == "admin" } else if { input.role == "user" input.action == "read" } else { false # Deny everyone else }

# Else with value: message := "Admin access" if { input.role == "admin" } else := "User access" if { input.role == "user" } else := "Access denied"

# Invalid else: # BAD: allow if { input.role == "admin" } else { # else on new line without brace false }

# GOOD: allow if { input.role == "admin" } else { false }

# else must follow } immediately: allow if { ... } else if { ... } else { ... } ```

Step 10: Rego Syntax Verification Script

```bash # Create verification script: cat << 'EOF' > /usr/local/bin/check-rego-syntax.sh #!/bin/bash

POLICY=${1:-"policy.rego"}

echo "=== Check Syntax ===" opa check $POLICY 2>&1

echo "" echo "=== Parse Tree ===" opa parse $POLICY 2>&1 | head -30

echo "" echo "=== Package Declaration ===" head -1 $POLICY

echo "" echo "=== Imports ===" grep "^import" $POLICY || echo "No imports"

echo "" echo "=== Rules Defined ===" grep -E "^[a-z_]+( if| :=| contains)" $POLICY || grep -E "^[a-z_]+\s*{" $POLICY

echo "" echo "=== Comments Check ===" grep -E "^(//|/*)" $POLICY && echo "WARNING: Invalid comment syntax" || echo "Comments OK"

echo "" echo "=== Operators Check ===" grep -E "(===|<>|= )" $POLICY && echo "WARNING: Invalid operators" || echo "Operators OK"

echo "" echo "=== Test Run ===" opa test $POLICY -v 2>&1 | tail -10

echo "" echo "=== Recommendations ===" echo "1. Add package declaration at file start" echo "2. Use == for comparison (not = or ===)" echo "3. Use # for comments (not // or /* */)" echo "4. Ensure braces {} are matched" echo "5. Use some for iteration (not for) echo "6. Add imports for new keywords" echo "7. Write tests for validation" EOF

chmod +x /usr/local/bin/check-rego-syntax.sh

# Usage: /usr/local/bin/check-rego-syntax.sh policy.rego ```

Rego Syntax Checklist

CheckExpected
Package declarationFirst non-comment line
Comparison operators== != < > <= >=
Comments# not // or /* */
Braces matched{} paired correctly
Iterationsome keyword
Importsfuture.keywords.*
Rulesidentifier if { }
Functionsname(args) if { }

Verify the Fix

```bash # After fixing Rego syntax errors

# 1. Parse policy opa parse policy.rego // Parse tree output (no errors)

# 2. Check policy opa check policy.rego // No errors

# 3. Evaluate policy opa eval -d policy.rego 'data.package.allow' // Returns result

# 4. Run tests opa test policy.rego -v // Tests pass

# 5. Use in OPA/Gatekeeper // Policy loads successfully ```

  • [Fix OPA Policy Evaluation Error](/articles/fix-opa-policy-evaluation-error)
  • [Fix OPA Gatekeeper Violation False](/articles/fix-opa-gatekeeper-violation-false)
  • [Fix Kubernetes Admission Webhook Failed](/articles/fix-kubernetes-admission-webhook-failed)