Have cached the configuration files in production ?
php artisan optimize
Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.
I'm using Laravel and React JS. In development, everything works fine, but in production, I keep getting an error saying the Ably API key is missing, even though it's present in the .env file in production. I've already checked and confirmed that it's there.
const Messaging = () => {
const { users, conversations, otherUserId, otherUser, ablyApiKey, auth } =
usePage().props;
console.log("Environment:", process.env.NODE_ENV);
console.log("Ably API Key loaded:", ablyApiKey ? "Yes" : "No");
if (!ablyApiKey) {
console.error("Ably API key is missing. Check the environment variables or configuration settings.");
if (process.env.NODE_ENV === "development") {
// Only log these details in development to avoid leaking sensitive info in production
console.error("Check server logs or deployment configuration to ensure API key is being set.");
}
}
useEffect(() => {
if (otherUser && ablyApiKey) {
console.log("Setting up Ably with API Key:", ablyApiKey);
const channelName = `private-chat-${Math.min(auth.user.id, otherUser.id)}-${Math.max(auth.user.id, otherUser.id)}`;
const ably = new Ably.Realtime.Promise({
key: ablyApiKey,
clientId: auth.user.id.toString(),
});
const channel = ably.channels.get(channelName);
channel.subscribe("message", (message) => {
if (message.data.from_user_id !== auth.user.id) {
setMessages((prevMessages) => [...prevMessages, message.data]);
}
});
return () => {
console.log("Unsubscribing from Ably channel:", channelName);
channel.unsubscribe();
};
} else if (!ablyApiKey) {
console.error("Unable to set up Ably communication due to missing API key.");
}
}, [otherUser, ablyApiKey, auth.user]);
const handleUserClick = async (user) => {
router.get(route("messaging.conversation.show", user.id), {
preserveState: true,
replace: true,
onSuccess: (response) => {
setData("to_user_id", user.id);
setSelectedUserId(user.id);
setSelectedUser(user);
setMessages(response.props.messages || []);
},
onError: (errors) => {
if (errors.status === 409) {
alert("A conflict occurred. Please try again.");
} else {
console.error("An error occurred: ", errors);
}
},
});
};
backend:
public function getConversation($otherUserId)
{
$userId = auth()->id();
$user = auth()->user()->load(['notifications','media', 'createdTags', 'createdNotes' => function($qry) use ($otherUserId){
$qry->where('to_user_id', $otherUserId);
}]);// Redirect if the user is not authenticated
if (!$user) {
return redirect()->back()
->with('message', 'Page not found.')
->with('type', 'error');
}
$users = $this->getContacts($userId);
// Update all unread messages to the other user in the conversation as read
Message::where('from_user_id', $otherUserId)
->where('to_user_id', $userId)
->whereNull('read_at')
->update(['read_at' => now()]);
Notification::where('user_id', $userId)
->where('type', 'message_update')
->update(['read' => true]);
$messages = Message::with(['media', 'replyTo.media', 'replyTo.sender']) // Load media, replyTo and replyTo.sender
->where(function($query) use ($userId, $otherUserId) {
$query->where('from_user_id', $userId)->where('to_user_id', $otherUserId);
})
->orWhere(function($query) use ($userId, $otherUserId) {
$query->where('from_user_id', $otherUserId)->where('to_user_id', $userId);
})
->orderBy('created_at', 'asc')
->get()
->map(function($message) use ($userId){
$isCurrentUser = $message->from_user_id === $userId;
return [
'id' => $message->id,
'message' => $message->message,
'from_user_id' => $message->from_user_id,
'name' => $isCurrentUser ? 'You' : $message->sender->name,
'read_at' => $message->read_at,
'timestamp' => $message->created_at->toISO8601String(),
'media' => $message->media,
'isCurrentUser' => $isCurrentUser,
'reply_to' => $message->replyTo ? [
'id' => $message->replyTo->id,
'message' => $message->replyTo->message,
'name' => $message->replyTo->sender->name,
'media' => $message->replyTo->media,
] : null,
];
});
$otherUser = User::with('media', 'assignedTags')->findOrFail($otherUserId);
return Inertia::render('Messaging/index', [
'users' => $users,
'conversations' => $messages,
'selectedUserId' => $otherUserId,
'otherUserId' => $otherUserId,
'otherUser' => $otherUser,
'ablyApiKey' => env('ABLY_API_KEY'),
]);
}
You are using the env() helper outside the config files. That's a no-no and the reason why the value doesn't work when config is cached.
https://laravel.com/docs/11.x/helpers#method-env
Add a config entry and use that instead, e.g. config('app.ably-api-key'). Then rebuild to config cache by running php artisan config:cache or php artisan optimize.
Please or to participate in this conversation.