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
| Aspect | Permission | Middleware |
|---|---|---|
| Purpose | Authorization | Request processing |
| Throws errors | Should throw for denied access | Can throw or handle errors |
| Return value | None (void) | Can modify response |
| Execution | Before handler | Can wrap handler |
Common Mistakes
- Using a regular function instead of
pikkuPermission - Not throwing an error when permission is denied
- Confusing permissions with middleware
- Providing
nullorundefinedas a permission
Related Errors
- PKU685 - Middleware Handler Invalid