Skip to main content

PKU835: Permission Handler Invalid

Error Message

[PKU835] Handler for pikkuPermission is not a function.

What Went Wrong

You're trying to register a permission check, but the provided handler is not a valid function. Permissions must be wrapped with pikkuPermission().

How to Fix

Use pikkuPermission to define your permission checks:

import { pikkuPermission } from '#pikku'

// ✅ Correct: Valid permission check
export const canCreateUser = pikkuPermission(async (ctx) => {
if (!ctx.session?.isAdmin) {
throw new Error('Only admins can create users')
}
})

Then use it in your routes:

import { wireHTTP } from '@pikku/core/http'
import { createUser } from './handlers'
import { canCreateUser } from './permissions'

wireHTTP({
method: 'post',
route: '/api/users',
func: createUser,
permissions: [canCreateUser], // Apply permission check
})

Permission Factory Pattern

For parameterized permissions, use pikkuPermissionFactory:

import { pikkuPermissionFactory } from '#pikku'

// Factory that creates permission checks
export const hasRole = pikkuPermissionFactory((requiredRole: string) => {
return pikkuPermission(async (ctx) => {
const userRole = ctx.session?.role
if (userRole !== requiredRole) {
throw new Error(`Required role: ${requiredRole}`)
}
})
})

// Usage
wireHTTP({
method: 'delete',
route: '/api/users/:id',
func: deleteUser,
permissions: [hasRole('admin')], // Create permission with parameter
})

Common Permission Patterns

Role-Based Permissions

export const isAdmin = pikkuPermission(async (ctx) => {
if (ctx.session?.role !== 'admin') {
throw new Error('Admin access required')
}
})

export const isUser = pikkuPermission(async (ctx) => {
if (!ctx.session?.userId) {
throw new Error('User must be logged in')
}
})

Resource Ownership Permissions

export const ownsResource = pikkuPermissionFactory((resourceId: string) => {
return pikkuPermission(async (ctx) => {
const resource = await getResource(resourceId)
if (resource.ownerId !== ctx.session?.userId) {
throw new Error('You do not own this resource')
}
})
})

Feature Flag Permissions

export const hasFeature = pikkuPermissionFactory((feature: string) => {
return pikkuPermission(async (ctx) => {
const features = await getUserFeatures(ctx.session?.userId)
if (!features.includes(feature)) {
throw new Error(`Feature not enabled: ${feature}`)
}
})
})

Permission vs Middleware

AspectPermissionMiddleware
PurposeAuthorizationRequest processing
Throws errorsShould throw for denied accessCan throw or handle errors
Return valueNone (void)Can modify response
ExecutionBefore handlerCan wrap handler

Common Mistakes

  • Using a regular function instead of pikkuPermission
  • Not throwing an error when permission is denied
  • Confusing permissions with middleware
  • Providing null or undefined as a permission
  • PKU685 - Middleware Handler Invalid