¿Tus suscripciones de SQL Server Reporting Services dejan de ejecutarse porque la programación compartida aparece como Expired aun sin fecha de finalización? Este artículo explica las causas reales y cómo solucionarlo de manera definitiva, paso a paso y con ejemplos prácticos.
Resumen del problema
En entornos de SSRS, las shared schedules permiten centralizar la ejecución de suscripciones. De forma inesperada, algunas de ellas cambian su estado a Expired
. Ese cambio detiene todas las suscripciones vinculadas, provocando informes desactualizados y alertas en cascada. El síntoma más común es un registro de ejecución vacío y la ausencia de nuevos archivos PDF o correos programados. Aunque la interfaz web muestre “Sin fecha de finalización”, internamente pueden existir condiciones que SSRS interpreta como caducidad.
Por qué un schedule sin fecha termina en “Expired”
Categoría | Explicación breve |
---|---|
Servicio | SQL Server Agent está detenido, reiniciado con errores o perdió conexión temporal con SSRS. El reloj de “siguiente ejecución” queda en el pasado y SSRS marca el schedule como expirado para evitar bucles infinitos. |
Configuración interna | La columna EndDate de ReportServer.dbo.Schedule no es NULL por ediciones manuales, restauraciones o scripts de migración, aun cuando la GUI no lo refleje. |
Hora/fecha del servidor | Si el reloj del sistema se adelanta (por ejemplo, tras un problema de NTP), la próxima ejecución calculada se sitúa “en el pasado” y SSRS fuerza el estado Expired . |
Corrupción o huérfanos | Programaciones clonadas, migradas o repetidamente editadas generan entradas huérfanas que SSRS limpia marcándolas como expiradas. |
Cómo diagnosticar el estado Expired paso a paso
Verificar el servicio SQL Server Agent
- Ejecuta
services.msc
oGet-Service -Name SQLSERVERAGENT
para confirmar que el servicio está Running. - Revisa el Error Log del Agent: si observas errores de autenticación o timeouts coincidentes con la hora en que cambió el estado, esa es la raíz del problema.
- Comprueba que el Account del servicio tenga permisos de lectura en la base de ReportServer y que pertenezca al rol
RSExecRole
.
Consultar la tabla ReportServer.dbo.Schedule
Abre SSMS y ejecuta la siguiente consulta para detectar programaciones con fecha de fin engañosa:
SELECT ScheduleID,
Name,
StartDate,
EndDate,
LastRunTime,
Status
FROM ReportServer.dbo.Schedule
WHERE Status = 'Expired'
OR EndDate <> NULL;
Si un schedule recurrente tiene EndDate
distinto de NULL
cuando no debería, actualízalo:
UPDATE ReportServer.dbo.Schedule
SET EndDate = NULL,
Status = 'Ready'
WHERE ScheduleID = 'GUIDDELSCHEDULE';
Tras la corrección, forzar una ejecución manual de la suscripción ayuda a validar el arreglo.
Revisar hora y zona horaria
- En servidores Windows, ejecuta
w32tm /query /status
para comprobar la sincronización NTP. - En entornos virtualizados, comprueba que el host y los nodos invitados compartan la misma zona horaria.
- Para scale‑out, verifica cada nodo SSRS: basta un solo servidor adelantado para que todos los schedules se marquen como pasados.
Auditar los registros (logs)
Los logs son tu mejor aliado:
- SSRS:
%ProgramFiles%\Microsoft SQL Server\MSRS*.MSSQLSERVER\Reporting Services\LogFiles
- SQL Server Agent: Management Studio > SQL Server Agent > Error Logs
- Event Viewer: Application log para verificar detenciones inesperadas del servicio
Filtra por la cadena “Schedule Expired
” o por el ScheduleID
. El timestamp indica el momento exacto en que cambió el estado, lo que suele coincidir con:
- Un reinicio del servidor
- Una alteración de la hora del sistema
- Actualizaciones de Windows que detuvieron servicios
Recrear y observar
Si el schedule parece irrecuperable o su GUID
está presente varias veces en la tabla Subscriptions
, elimínalo desde el portal web o vía script:
EXEC ReportServer.dbo.DeleteSchedule 'GUIDDELSCHEDULE';
Luego crea uno nuevo con la misma periodicidad. Observar la primera ejecución suele bastar para concluir si el problema era un schedule corrupto (se mantiene activo) o de infraestructura (vuelve a expirar).
Actualizar SSRS y parches
En las versiones 2014 y 2016 sin CU acumulativos, existe un bug documentado que marca como Expired
cualquier schedule que supera los 32 767 disparos. Instalar el CU16+ o migrar a una versión posterior elimina este límite. Verifica la compilación con:
SELECT @@VERSION AS Build;
Automatizar la detección con PowerShell
Mantener cientos de schedules manualmente es poco viable. El script siguiente envía un correo cuando detecta nuevos schedules con estado Expired
:
Import-Module SqlServer
$query = @"
SELECT Name, LastRunTime
FROM ReportServer.dbo.Schedule
WHERE Status = 'Expired'
"@
$result = Invoke-Sqlcmd -ServerInstance "MI_SERVIDOR" -Database "ReportServer" -Query $query
if ($result.Count -gt 0) {
Send-MailMessage -SmtpServer "smtp.miempresa.com" `
-To "dba@miempresa.com" `
-From "ssrs-monitor@miempresa.com" `
-Subject "Alerta SSRS: Schedules Expired" `
-Body ($result | Out-String)
}
Programa ese script cada 30 min con el Task Scheduler o con un Job del propio SQL Agent para recibir alertas proactivas.
Preguntas frecuentes
¿Una programación “One Time” expira siempre?
Sí. Está diseñada para ello. Tras ejecutarse, pasa a Expired
. Para pruebas repetitivas usa “Daily” o “Hourly”.
¿Qué sucede con las suscripciones ligadas?
Cuando el schedule está expirado, las filas de la tabla Subscriptions
permanecen, pero SSRS las ignora hasta que asignes un nuevo schedule.
¿Puede una herramienta externa como SCCM cambiar el reloj?
Sí. Políticas de dominio o scripts de arranque pueden ajustar la hora. Cualquier variación que lleve la hora del sistema al futuro generará un disparo “perdido” y SSRS lo marcará como expirado.
¿Es necesario reiniciar el servicio tras editar la tabla Schedule?
No. SSRS lee la tabla cada pocos segundos. Sin embargo, reiniciar el servicio limpia la caché y acelera la detección de cambios.
Buenas prácticas para prevenir la expiración inesperada
- Monitorizar el Agent: habilita alertas de servicio detenido o reiniciado.
- Sincronizar relojes: implementa NTP redundante y compara la deriva diariamente.
- Evitar ediciones directas en la tabla
Schedule
. Usa siempre la API o el portal web. - Auditar migrations: tras una restauración, inspecciona
Schedule
ySubscriptions
para detectarEndDate
involuntarios. - Actualizar SSRS: mantén la versión dentro de soporte y aplica CUs trimestrales.
- Planificar revisiones: genera un informe mensual que liste schedules a punto de expirar según su
EndDate
.
Ejemplo de informe de control interno
Crea un informe simple en SSRS que consuma esta consulta:
SELECT s.Name AS ScheduleName,
u.UserName AS Owner,
s.StartDate,
ISNULL(s.EndDate,'Sin fin') AS EndDate,
s.LastRunTime,
s.Status
FROM ReportServer.dbo.Schedule s
LEFT JOIN ReportServer.dbo.Users u
ON s.OwnerID = u.UserID
ORDER BY s.Status, s.LastRunTime DESC;
Publícalo bajo la carpeta Administración y asígnale un schedule semanal independiente. Si este informe deja de llegar, es la señal inequívoca de que tu entorno vuelve a tener schedules expirados.
Conclusión
Las programaciones compartidas son el corazón de la automatización en SSRS. Cuando aparecen como Expired
sin razón aparente, la causa suele esconderse en el servicio Agent, en la zona horaria o en la tabla Schedule
. Siguiendo los pasos de verificación, corrección y monitorización descritos, puedes restaurar la ejecución automática de tus informes y evitar interrupciones futuras. Implementa alertas proactivas, mantén actualizado tu entorno y documenta cada cambio para que la próxima vez el estado Expired sea solo un recuerdo.