SSRS: Programaciones compartidas “Expired” sin fecha de fin – causas y solución detallada

¿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.

Índice

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íaExplicación breve
ServicioSQL 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 internaLa 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 servidorSi 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érfanosProgramaciones 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 o Get-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:

  1. Un reinicio del servidor
  2. Una alteración de la hora del sistema
  3. 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 y Subscriptions para detectar EndDate 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.

Índice